C#在运行时返回不带类型参数的泛型类型

时间:2016-02-02 21:34:07

标签: c# generics return

是否可以返回

类型的对象
 IModel< T >

不知道类型参数?

将对象存储在字典中,将Type作为键,将IModel(作为IModel<T>的基接口)的对象实现为值。 接口IModel<T>继承自IModel,但要执行完整操作,我需要IModel<T>的对象。 T需要有IFactoryItem接口。

但首先是代码:

    public IModel<T> GetModel<T>() where T : IFactoryItem
    {
         Type tmpType  = typeof(T);
         if (!_allModelsByType.ContainsKey(tmpType))
                return null;

         return (IModel<T>)_allModelsByType[tmpType];
    }

我想到了像

这样的解决方案

public IModel GetModel(Type t)和一个将其强制转换为正确类型的包装器。

我希望我并非完全错误。 这是我的第一个问题。

2 个答案:

答案 0 :(得分:1)

如果您的问题是如何返回IModel<T>的实例,但您在编译时不知道T是什么,只是它始终来自IFactoryItem然后:

如果您未在方法输入中使用T,并且T是一个类,则可以使用协方差:

public interface IModel<out T> where T : class
{
    T Value { get; }
}

public class Model<T> : IModel<T> where T : class
{
    public T Value { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        var foo = new Model<string>()
        {
            Value = "hello world",
        };

        IModel<object> boo = foo;

        Console.WriteLine(boo.Value);
    }
}

通过这种方式,您可以传递IModel<IFactoryItem>而不是IModel<T>

如果您需要值类型,或者您不能使用协方差,那么理想情况下您(如您所建议的那样)第二个非通用接口IModel将任何值公开为{{ 1}}

object

如果您的问题是如何在运行时只知道类型时创建public interface IModel { object Value { get; } } public class Model<T> : IModel, IModel<T> { public T Value { get; set; } object IModel.Value => Value; } 的实例,那么:

Model<T>

您仍然需要返回 var someType = typeof (SomeFactoryItem); var instance = Activator.CreateInstance(typeof (Model<>).MakeGenericType(someType)); ,或者,如果您可以使用协变,IModel

答案 1 :(得分:0)

  

是否可以在不知道类型参数的情况下返回IModel<T>类型的对象?

技术上没有,但我认为实际上这是一个轻微的误解。 T 的类型知道,它只是通用的 - 实际上它是众所周知的,它甚至受到约束。请注意where T : IFactoryItem,这表示尝试执行AddModelGetModel函数的任何内容都必须是实现IFactoryItem接口的内容。如果您尝试编写调用任一方法的内容并将其传递给除IFactoryItem接口的实现之外的任何内容,它甚至不会编译。

请考虑下面的代码,变量即fetch实际上是与添加的变量model相同的对象!

class Program
{
    static void Main()
    {
        var test = new Test();
        var model = new Model();
        test.AddModel(model);
        var fetch = test.GetModel<FactoryItem>();

        Console.WriteLine(fetch == model 
                              ? "It does in fact work..." 
                              : "Uh, that was supposed to work?");
        Console.ReadLine();
    }

    public class Test
    {
        private readonly Dictionary<Type, object> _allModelsByType;

        public Test()
        {
            _allModelsByType = new Dictionary<Type, object>();
        }

        public void AddModel<T>(IModel<T> model) where T : IFactoryItem
        {
            _allModelsByType.Add(typeof(T), model);
        }

        public IModel<T> GetModel<T>() where T : IFactoryItem
        {
            var tmpType = typeof(T);
            return _allModelsByType.ContainsKey(tmpType)
                ? _allModelsByType[tmpType] as IModel<T>
                : null;
        }
    }
}

internal class FactoryItem : IFactoryItem { }

internal class Model : IModel<FactoryItem>
{
    public FactoryItem Value { get; set; }
}

internal interface IFactoryItem { }

internal interface IModel<T> where T : IFactoryItem
{
    T Value { get; set; }
}

运行此程序将输出&#34;它确实有效...&#34;

&#13;
&#13;
<iframe width="100%" height="750" src="https://dotnetfiddle.net/Widget/J26ETn" frameborder="0"></iframe>
&#13;
&#13;
&#13;