我最近创建了一个接口层从业务逻辑层区分DataAccessProvider。 通过这种方法,每当我们想通过在Web / App.Config中改变的值,我们可以改变我们的选择DataAccessProvider的。 (可以给出更多的细节如果需要的话)。
总之,要做到这一点,我们使用反射来实现我们的DataProvider类上,我们可以工作。
/// <summary>
/// The constructor will create a new provider with the use of reflection.
/// If the assembly could not be loaded an AssemblyNotFoundException will be thrown.
/// </summary>
public DataAccessProviderFactory()
{
string providerName = ConfigurationManager.AppSettings["DataProvider"];
string providerFactoryName = ConfigurationManager.AppSettings["DataProviderFactory"];
try
{
activeProvider = Assembly.Load(providerName);
activeDataProviderFactory = (IDataProviderFactory)activeProvider.CreateInstance(providerFactoryName);
}
catch
{
throw new AssemblyNotFoundException();
}
}
但现在我不知道如何反映速度慢是什么?
在大多数情况下:比速度不够快了。 例如,如果你正在使用此创建一个DAL包装对象,所花费的时间来创建对象通过比较,它需要连接到网络的时间思考将是微不足道的 。 所以优化,这将是浪费时间。
如果你是在一个紧密的循环使用反射,有技巧,以提高它:
- 泛型(使用包装器
where T : new()
和MakeGenericType
) -
Delegate.CreateDelegate
(到类型化的代表;不适用于构造工作) -
Reflection.Emit
-铁杆 -
Expression
(如Delegate.CreateDelegate
,但更灵活,适用于构造函数)
但是,你的目的, CreateInstance
是完全正常的。 与坚持,并让事情变得简单。
编辑:边长约相对表现点保持,同时最重要的事情,“衡量”,仍然是,我要澄清上述一些。 有时候......这非常重要。 第一项措施。 不过,如果你发现这是太慢了,你可能想看看像FastMember ,它完成所有Reflection.Emit
代码在后台悄悄,给你一个很好的方便的API; 例如:
var accessor = TypeAccessor.Create(type);
List<object> results = new List<object>();
foreach(var row in rows) {
object obj = accessor.CreateNew();
foreach(var col in cols) {
accessor[obj, col.Name] = col.Value;
}
results.Add(obj);
}
这是简单的,但会非常快。 在具体的例子中,我提到关于DAL包装,如果你正在做这个地段,可以考虑像短小精悍 ,再次完成所有Reflection.Emit
后台代码给你以最快的速度,但易于使用的API:
int id = 12345;
var orders = connection.Query<Order>(
"select top 10 * from Orders where CustomerId = @id order by Id desc",
new { id }).ToList();
其慢相比非反射码。 最重要的是,如果不是它的速度慢,但如果它的缓慢重要的地方 。 例如,如果你使用实例在网络环境反射,其中预计并发性可以上升到10K的对象,这将是缓慢的。
无论如何,其良好的不被关注提前表现。 如果事情原来是缓慢的,你总是可以加速它们,如果你设计正确的事情,这样,你预计可能在未来需要优化的部分本地化。
如果您需要加快您可以检查这个著名的文章:
动态......但快速:三只猴子,狼和DynamicMethod的和的ILGenerator类的故事
反思是不慢。 由反射调用一个方法是比正常方式慢大约3倍。 如果你这样做只是一次或在非紧急情况下是没有问题的。 如果你在一个时间关键方法使用10000次,我会考虑改变实现。
我想我会做一个简单的测试来证明反射有多慢是相对于没有。
与反思
- 通过他们的每一个属性和匹配的迭代实例化对象58
总时间:52254纳秒
while (reader.Read()) { string[] columns = reader.CurrentRecord; CdsRawPayfileEntry toAdd = new CdsRawPayfileEntry(); IEnumerable<PropertyInfo> rawPayFileAttributes = typeof(CdsRawPayfileEntry).GetProperties().Where(prop => Attribute.IsDefined(prop, typeof(CustomIndexAttribute))); foreach (var property in rawPayFileAttributes) { int propertyIndex = ((CustomIndexAttribute)property.GetCustomAttribute(typeof(CustomIndexAttribute))).Index; if (propertyIndex < columns.Length) property.SetValue(toReturn, columns[propertyIndex]); else break; } }
没有反射
- 通过创建一个新的对象实例化对象58
总时间:868纳秒
while (reader2.Read()) { string[] columns = reader2.CurrentRecord; CdsRawPayfileEntry toAdd = new CdsRawPayfileEntry() { ColumnZero = columns[0], ColumnOne = columns[1], ColumnTwo = columns[2], ColumnThree = columns[3], ColumnFour = columns[4], ColumnFive = columns[5], ColumnSix = columns[6], ColumnSeven = columns[7], ColumnEight = columns[8], ColumnNine = columns[9], ColumnTen = columns[10], ColumnEleven = columns[11], ColumnTwelve = columns[12], ColumnThirteen = columns[13], ColumnFourteen = columns[14], ColumnFifteen = columns[15], ColumnSixteen = columns[16], ColumnSeventeen = columns[17] }; }
虽然,不是完全公平的,因为反射也有创造通过反射一个新的对象上检索每个属性58 * 18倍的特定属性,但它至少提供了一些观点。
除了以下在其他的答案中给出的链接,并确保你不写“pathalogically坏”的代码,那么对我来说,这个最好的答案就是测试它自己。
只有你知道你在哪里瓶颈是,你的反射代码多少次是用户,反射代码是否会在紧张的循环等。你知道你的业务的情况下,很多用户将如何访问您的网站,什么PERF要求。
然而,考虑到你这里显示然后我的猜测是,反射的开销不会是一个巨大的问题的代码段。
VS.NET的网络测试和性能测试功能,应测量该代码非常简单的性能。
如果你不使用反射,你会你的代码是什么样子? 将它有什么限制? 这可能是因为你不能与你发现自己如果去掉反射代码的限制居住。 这可能是值得尝试设计这个代码,而不反射,看是否有可能或它的另一种方法是可取的。
我是做somethign相似,直到我开始与国际奥委会玩。 我会用Spring的对象定义指定数据提供商 - SQL,XML,或嘲弄!