簡體   English   中英

通用接口繼承轉換

[英]Generic interface inheritance castings

當前,我面臨一個通用接口繼承問題:

interface IParent<T> {
    R Accept<R>(IParentVisitor<T, R> visitor);
}

interface IChild<T, TKey> : IParent<T> {
   R Accept<R>(IChildVisitor<T, TKey, R> visitor);
}

我還創建了以下Visitor接口:

interface IParentVisitor<T, R> {
    R Visit(IParent<T> parent);
}

interface IChildVisitor<T, TKey, R> : IParentVisitor<T, R> {
    R Visit(IChild<T, TKey> viz);
}

實現方式:

class ParentVisitor<T> : IParentVisitor<T, MyResultClass> {
    MyResultClass Visit(IParent<T> parent) {
      return //...;
    }
}

class ChildVisitor<T, TKey> : IChildVisitor<T, TKey, MyAnotherResultClass> {
    MyAnotherResultClass Visit(IChild<T, TKey> child) {
      return //...;
    }
}

到目前為止,一切似乎都是正確的。 但是,請猜測這種情況:

static void Main() {
    IList<IParent<MyT>> interfaces = new List<IParent<MyT>>();
    interfaces.add(new Parent<MyT>());
    interfaces.add(new Child<MyT, string>());
    interfaces.add(new Child<MyT, int>());
    interfaces.add(new Child<MyT, TimeSpan>());
    //...

    //(!!*!!)
    foreach (IChild<MyT, string> stringChild in interfaces.OfType<IChild<MyT, string>()) {
      ChildVisitor stringChildVisitor = new ChildVisitor<MyT, string>();
      var result = stringChild.Accept(stringChildVisitor);
      //...
    }

    //(!!*!!)
    foreach (IChild<MyT, int> intChild in interfaces.OfType<IChild<MyT, int>()) {
      ChildVisitor intChildVisitor = new ChildVisitor<MyT, int>();
      var result = stringChild.Accept(intChildVisitor);
      //...
    }

    //and so on up to infitiny types in C#...
}

我認為這是獲取我想要的東西的不可行方法。

我想要獲得的是對IChild<T, *>上的任何一個使用ChildVisitor ,其中*是任何類型。 我不知道我的解釋是否很好。

像這樣:

//(!!*!!)
foreach (IChild<MyT, *> asterisckChild in interfaces.OfType<IChild<MyT, *>()) {
  ChildVisitor asterisckChildVisitor = new ChildVisitor<MyT, *>();
  var result = asterisckChild.Accept(asterisckChildVisitor);
  //...
}

有任何想法嗎?

IList list = new ArrayList();
list.Add(new Dictionary<string, string>
{
    ["key"] = "value"
});
list.Add(new Dictionary<string, int>()
{
    ["key"] = 123
});
list.Add("just for the test");

foreach(var it in list)
{
    foreach(var face in it.GetType().GetInterfaces())
    {
        //1. Filter out non-generic interfaces
        // (following GetGenericTypeDefinition() would throw exception otherwise)
        if (!face.IsGenericType)
            continue;

        //2. Filter out anything that is not IDictionary<,>
        if (typeof(IDictionary<,>) != face.GetGenericTypeDefinition())
            continue;

        //3. Filter out anything that is not IDictionary<string,>
        var generic = face.GetGenericArguments();
        if (typeof(string) != generic[0]) //note: consider IsAssignableFrom instead
            continue;

        //4. Invoke the method
        var valueType = generic[1];
        var method = face.GetMethod("TryGetValue"); //note: needs to be more specific if overloaded

        //don't know how you want to choose R for the Accept<R>
        //method = method.MakeGenericMethod(new[] { typeof(R) });

        var arguments = new object[] { "key", null };
        method.Invoke(it, arguments);
        var value = arguments[1];

        //5. Do something with the result
        Console.WriteLine(value.ToString());
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM