3

ジェネリック子コレクションの再帰的注入を行うValueInjecterのカスタム注入クラスを作成しましたが、VI サイトの「CloneInjection」サンプルのように複製するのではなく、既存のターゲット オブジェクトで動作します。ただし、現在、既知の型 (ICollection<MyTargetType>) にキャストしているため、インジェクション クラスはハード コードされた 1 つの型にのみ適しています。ジェネリックを動的にキャストする方法を理解できないようですが、何か提案はありますか? 「RecursiveInjection」クラスの 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;
  }
}

ありがとう、DanO

4

3 に答える 3

1

ジェネリック コレクションを動的にキャストする方法を見つけることはできませんでしたが、解決しようとしていた根本的な問題の解決策を発見しました。それは、子コレクションを含む EF POCO オブジェクト (1 対多の"ナビゲーション プロパティ")。

EF 4.0 から EF 4.1 にアップグレードしたところです。EF 4.1 は、現在、子コレクションでのオブジェクトのマージを実際に管理しています。アップグレード後、CloneInjection をそのまま使用できるようになりました。

于 2011-05-04T21:40:08.213 に答える
1

ICollection を使用し、比較のために 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 ) );
于 2011-05-03T04:48:09.560 に答える
0

これがあなたが探しているものだと思います:

    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 を使用してこれを少し短くすることができます

于 2011-05-07T13:52:13.973 に答える