111,088
社区成员




lock (Users)
{
string user;
if (!Users.TryGetValue(1, out user))
{
Users.Add(1, "张三");
}
}
因捕捉异常,产生的跟踪所花的时间更长,当然什么都需要测式出来证明,你创建多个线程试一下。
使用哪个字典都不是你这个IoC性能的最大问题,Ioc最大的还是创建对象,特别是不确定的构造参数,这种是比较麻烦的,楼主的这个各种构造参数都只会调用这个(类型 + 别名)的首个编译委托.
[quote]
trygetValue和tryCatch的性能问题在我的另外一篇帖子中已经证明了。所以我这里不再多说。
下面是这个的链接
http://bbs.csdn.net/topics/390624824
对于不确定参的构造函数,其实我这里是支持不确定参的。
但是我有些地方出于某些特殊的原因(例如委托缓存等如果支持多参将会增加缓存的复杂度。)
并且由于Di的存在,所以我认为多构造函数的情况属于很特殊的例子。并且我们也可以将多构造函数转为1个足够健壮的构造函数.所以只支持单构造函数。
当然,对于普通的实例注册我并没有Check构造函数的数量。这个是一个bug.但是对于装饰者和Di的注册,我都验证了构造函数的数量,如果大于1将会抛出一个异常。
lock (Users)
{
string user;
if (!Users.TryGetValue(1, out user))
{
Users.Add(1, "张三");
}
}
因捕捉异常,产生的跟踪所花的时间更长,当然什么都需要测式出来证明,你创建多个线程试一下。
使用哪个字典都不是你这个IoC性能的最大问题,Ioc最大的还是创建对象,特别是不确定的构造参数,这种是比较麻烦的,楼主的这个各种构造参数都只会调用这个(类型 + 别名)的首个编译委托.
创建一个简单的具有三种构造参数的对象(接口就不用写了)
public class Orders : IOrders
{
public Orders()
{
}
public Orders(int ordersID)
{
this.OrdersID = ordersID;
}
public Orders(int ordersID, string clientele)
{
this.OrdersID = ordersID;
this.Clientele = clientele;
}
public Orders(int ordersID, string clientele, double value)
{
this.OrdersID = ordersID;
this.Clientele = clientele;
this.Value = value;
}
public virtual int OrdersID { get; set; }
public double Value { get; set; }
public virtual string Clientele { get; set; }
}
注册:
Factory factory = Factory.GetInst();
factory.Regist<IOrders, Orders>("a", IOCFactoryModel.InstType.Normal);
调用:当调用到第二个时就出现异常了,因为首个委托需要三个参数,而第二次调用只要一个参数,所以就出现了索引不存在的异常。因为首个编译的委托需要三个参数。这也就是我所说的,你只缓存了首个调用的构造信息委托。即使第二次不同的构造参数的上下文 Key 也与第一个相同才导致这个结果。
var factory = Factory.GetInst();
var o1 = factory.Get<IOrders>("a", 1, "张三", 9.0);
var o2 = factory.Get<IOrders>("a", 1); //产生异常
if (o2 != null)
{
}
其实要实现不仅仅是参数。
如具有如下构造,并且都能够识别出相关的构造调用,如果性能仍然是前者的 5 倍,那就很不错了。
[code=csharp]
public class U
{
public int User { get; set; }
}
public class U1:U
{
public string Id { get; set; }
}
public class Abc
{
public Abc(int a, string b)
{
}
public Abc(string a, int b, string c)
{
}
public Abc(int a, string b, string c)
{
}
public Abc(int a, string b, int? c)
{
}
public Abc(int a, U u)
{
}
public Abc abc(params object[] args)
{
//args 要能正确处理参数并解析调用哪个造构的委托。
return new Abc(1, (string)null);
return new Abc(1, (U)null);
return new Abc(1, new U1()); //U1继承U
return new Abc(null, 1, "");
return new Abc(1, null, (string)null);
return new Abc(1, null, (int?)null); //Nullable<int> 与 int
}
}
[/code]
var factory = IOCFactory.Factory.GetInst();
//使用 老赵的 代码计时
IOrders Orders = null;
CodeTimer.Time("IOCFactory 无构造参数", iteration, () =>
{
Orders = factory.Get<IOrders>("order");
});
//Orders.OrdersID 应该等于0,没有问题
CodeTimer.Time("IOCFactory 1个造参数", iteration, () =>
{
Orders = factory.Get<IOrders>("order", 1);
});
/* 同一实现对象的不同的构造 上下文 context.HashCode 是相同的,所有调用了首次生成的委托。
* Orders.OrdersID 应该等于1,但等于 = 0,即只调用首次生成对象的委托,虽然生成新的实例,但即是调用首次的创建对象的委托
* 这种在实际应用中要出问题的
*/
CodeTimer.Time("IOCFactory 2个造参数", iteration, () =>
{
Orders = factory.Get<IOrders>("order", 2, "张三");
});
//Orders.OrdersID 应该等于2,只可惜还是0
CodeTimer.Time("IOCFactory 3个造参数", iteration, () =>
{
Orders = factory.Get<IOrders>("order", 3, "张三", 9.0);
});
//Orders.OrdersID 应该等于3,但等于 = 0
另外:NormalInstCreator 这个类的可更新一下
将 Dictionary 改成 ConcurrentDictionary
private static Func<int, ObjectActivator> BuilderObjectActivator(RegistObjectContext context, params object[] param)
{
return (HashCode) =>
{
var types = new Type[param.Length];
for (int i = 0; i < param.Length; i++)
{
types[i] = param[i].GetType();
}
var constructor = context.ObjType.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, types, null);
return NormalInstCreator2.GetActivator(context.ObjType, constructor);
};
}
public object CreateInst(RegistObjectContext context, params object[] param)
{
// var fun = BuilderObjectActivator(context, param);
// fun(context.HashCode);
ObjectActivator objectCreater = dicCache.GetOrAdd(context.HashCode, BuilderObjectActivator(context, param));
return objectCreater(param);
}