简体   繁体   English

将泛型类转换为接口

[英]Cast generic class to interface

I have a problem with casting a generic class to the interface it is implementing.我在将泛型类转换到它正在实现的接口时遇到问题。

My code is like this:我的代码是这样的:

interface foo
{
    void foobar();
}

class bar: foo
{
    public void foobar()
    {
        throw new NotImplementedException();
    }
}

now I have my factory that creates instances of my classes by the interface, mostly a simple microkernel (service locator).现在我有我的工厂,它通过接口创建我的类的实例,主要是一个简单的微内核(服务定位器)。 I will simplify it here.我将在这里简化它。 Normally it will look up the implementing class from the configs and the factory take the type as T but that doesn't matter for the problem I have.通常它会从配置中查找实现类,工厂将类型作为 T 但这对我遇到的问题并不重要。

public static class Factory
{


    public static Lazy<foo> CreateLazyInstance()
    {
        Lazy<foo> instance;


        Type type = typeof(bar);

        Type lazyType = typeof(Lazy<>);
        Type toContruct = lazyType.MakeGenericType(type);

        instance = (Lazy<foo>)Activator.CreateInstance(toContruct);

        return instance;
    }
}

If will fail at:如果将失败:

instance = (Lazy<foo>)Activator.CreateInstance(toContruct);

and claim with an InvalidCastException that it is not possible to cast the type Lazy<bar> to Lazy<foo> .并使用 InvalidCastException 声明无法将类型Lazy<bar>Lazy<foo>

Is there any way to tell the CLR that this cast will work or to workaround this problem?有什么方法可以告诉 CLR 此演员表可以工作或解决此问题吗?

No - Lazy<T> is invariant - so a Lazy<string> is not a Lazy<object> for example.不 - Lazy<T>不变的- 例如, Lazy<string>不是Lazy<object> (As pointed out in comments, it couldn't be declared as covariant in T , as it's a class, not an interface or delegate.) (正如评论中所指出的,它不能在T声明为协变,因为它是一个类,而不是接口或委托。)

However, you can convert one to the other easily enough:但是,您可以轻松地将一个转换为另一个:

static Lazy<TOutput> CreateLazyProxy<TInput, TOutput>
    (Lazy<TInput> input) where TInput : TOutput
{
    return new Lazy<TOutput>(() => input.Value);
}

Also, Func<T> is covariant, so this will work too:此外, Func<T>协变的,所以这也适用:

static Lazy<TOutput> CreateLazy<TInput, TOutput>(Func<TInput> func)
    where TInput : TOutput
{
    return new Lazy<TOutput>(func);
}

(Not that you particularly need a method for that - if you've got a Func<TInput> , just construct a Lazy<TOutput> directly.) (并不是说你特别需要一个方法——如果你一个Func<TInput> ,直接构造一个Lazy<TOutput> 。)

An easier way to do this would be to pass in a lambda to the Lazy constructor.一种更简单的方法是将 lambda 传递给 Lazy 构造函数。 So, your code would look like the following:因此,您的代码如下所示:

  public static Lazy<foo> CreateLazyInstance()
  {
     Type type = typeof(bar);
     return new Lazy<foo>(() => (foo)Activator.CreateInstance(type));
  }  

You must do your foo generic parameter : new():你必须做你的 foo 通用参数:new():

public static Lazy<foo> CreateLazyInstance() where foo : new()

And change your code to find a constructor and call it:并更改您的代码以查找构造函数并调用它:

Type t = typeof(foo);
t.GetConstructor(new type[]{});
return (foo)t.Invoke(new object[]{});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM