自定义valueinjector注入中的动态类型转换
本文关键字:动态 类型转换 valueinjector 注入 自定义 | 更新日期: 2023-09-27 17:54:30
我已经为valueinjector创建了一个自定义注入类,它对泛型子集合进行递归注入,但它适用于现有的目标对象,而不是像VI站点上的"CloneInjection"样例那样克隆。但是,目前我正在将类型转换为已知类型(icollectionmytargettype),因此注入类只适用于一种硬编码类型。我似乎找不到一种方法来动态地转换泛型,有什么建议吗?下面是我的"递归注入"类的SetValue代码。
//for value types and string just return the value as is
if (c.SourceProp.Type.IsValueType || c.SourceProp.Type == typeof(string))
return c.SourceProp.Value;
if (c.SourceProp.Type.IsGenericType)
{
//handle IEnumerable<> also ICollection<> IList<> List<>
if (c.SourceProp.Type.GetGenericTypeDefinition().GetInterfaces().Contains(typeof(IEnumerable)))
{
var t = c.TargetProp.Type.GetGenericArguments()[0];
if (t.IsValueType || t == typeof(string)) return c.SourceProp.Value;
//get enumerable object in target
var targetCollection = c.TargetProp.Value as ICollection<MyTargetType>;
//possible to cast dynamically?
foreach (var o in c.SourceProp.Value as IEnumerable)
{
//get ID of source object
var sourceID = (int)o.GetProps().GetByName("ID").GetValue(o);
//find matching target object if there is one
var target = targetCollection.SingleOrDefault(x => x.ID == sourceID);
if (target != null)
{
target.InjectFrom<RecursiveInjection>(o);
}
}
return targetCollection;
}
}
谢谢,端午
我会使用ICollection和override Equals(object)来进行比较。
public class MyTargetType
{
public override bool Equals( object obj )
{
return ( obj is MyTargetType )
? this.ID == ( ( MyTargetType ) obj ).ID
: false;
}
}
那么在你的循环中,你将直接匹配对象,而不是使用反射。
var target = targetCollection.SingleOrDefault( x => x.Equals( o ) );
虽然我还不能找到一种方法来动态转换泛型集合,但我确实发现了一种解决方案来解决我试图解决的潜在问题,即注入包含子集合的EF POCO对象(一对多"导航属性")。
我刚刚从EF 4.0升级到EF 4.1,哈利路亚!EF 4.1现在实际管理子集合上的对象合并。升级后,我可以按原样使用CloneInjection。
我想这就是你要找的:
public class M1
{
public string Name { get; set; }
}
public class M2
{
public string Name { get; set; }
}
[Test]
public void Cast()
{
object source = new List<M1> {new M1 {Name = "o"}};
object target = new List<M2>();
var targetArgumentType = target.GetType().GetGenericArguments()[0];
var list = Activator.CreateInstance(typeof(List<>).MakeGenericType(targetArgumentType));
var add = list.GetType().GetMethod("Add");
foreach (var o in source as IEnumerable)
{
var t = Activator.CreateInstance(targetArgumentType);
add.Invoke(list, new[] { t.InjectFrom(o) });
}
target = list;
Assert.AreEqual("o", (target as List<M2>).First().Name);
}
在。net 4中,你可以通过使用dynamic