繁体   English   中英

C#-当泛型方法类型为接口时返回实现

[英]C# - Returning an implementation when generic method type is an Interface

这就是我要使用的方式:

var fooStuff = _foo.DoBarStuff().GetFooStuff(id);

我想在调用DoBarStuff()时返回实现,以便可以调用GetFooStuff(id)来获取fooStuff。

public interface IFoo() : IBar
{
    FooStuff GetFooStuff(int id);
}

public class Foo
{
    public FooStuff GetFooStuff(int id)
    {
        // get fooStuff
        return fooStuff;
    }     
}

public interface IBar
{
      T DoBarStuff<T>();
}

public class Bar
{
    public T DoBarStuff<T>()
    {
        // do bar stuff
        return T; 
    }
}

T是任何接口,当“返回T”时; 被执行,我需要它的实现返回。 现在,我在“ return T;”下的T下收到此错误; 线。

T是一种类型,在给定的上下文中无效。 类型参数名称此时无效。

谢谢!

这应该工作:

public interface IBar
{
    T DoBarStuff<T>() where T : class, new();
}

public class Bar : IBar
{
    public T DoBarStuff<T>() where T : class, new()
    {
        // do bar stuff
        return new T(); 
    }
}

但是,使用方法DoBarStuff时必须指定类型:

用法: var fooStuff = _foo.DoBarStuff<FooWhatEver>().GetFooStuff(id)


如果您不想这样做,请使用您的类/接口泛型:

public interface IBar<T> where T : class, new()
{
    T DoBarStuff<T>();
}

public class Bar<T> : IBar<T> where T : class, new()
{
    public T DoBarStuff()
    {
        // do bar stuff
        return new T(); 
    }
}

用法:

IBar bar = new Bar<FooWhatEver>();
var fooStuff = _foo.DoBarStuff().GetFooStuff(id);

但是所有这些都不适用于接口,仅适用于可实例化的类(具有默认构造函数)。

对于接口,您将需要一些东西来在它们及其实现之间进行转换。

简单的方法是使用字典(出于测试目的,但是您可以按照@N_tro_P的建议使用依赖项注入框架,即使现在在其中之一之间进行选择也不应该成为您的主要目标)。

您最终会得到这样的结果(不要忘记您的继承和通用部分):

public class Bar // <T> or not depending on your choice
// You can add this constraint to avoid value types (as int):
//   where T : class
{
    Dictionary<Type, Type> _container = new Dictionary<Type, Type>();
    {
        {typeof(IFoo), typeof(Foo)}
    };

    public T DoBarStuff() // <T> or not depending on your choice
    // You can add this constraint to avoid value types (as int):
    //   where T : class
    {
        // get fooStuff

        return Activator.CreateInstance(_container[typeof(T)]);
        // You will get an error if T is not in the container
        // or if _container[typeof(T)] is not instantiable
        // or doesn't have a default constructor.
    }
}

唯一的问题是,您将必须用要使用的所有接口/类填充字典/容器,处理起来会很烦人。 您可能希望使用我的第一种解决方案。

您可以执行此操作,但不能执行写呼叫签名的方式。

您从来没有让Bar不使用IBar,而Foo将其用作接口。 所以你应该改变它。 您可能会混淆如何与界面进行交互。

调整后的代码

public interface IFoo
{
    FooStuff GetFooStuff(int id);
}

public class Foo : IFoo
{
    public FooStuff GetFooStuff(int id)
    {
        // get fooStuff
        return fooStuff;
    }     
}

public interface IBar
{
      T DoBarStuff<T>();
}

public class Bar : IBar
{
    public T DoBarStuff<T>()
    {
        // do bar stuff
        return container[typeof(T)]; 
    }
}

您要使用的是确保您随后输入类型,例如这样。

var fooStuff = _foo.DoBarStuff<BarStuff>().GetFooStuff(id);

这就是依赖容器的工作方式。 他们在其中将使用类型作为键的实例化对象存储在Dictionary中。 即字典实例;

然后,您也可以将工厂存储在其他位置,但这需要您的符号匹配,或者您只是假设它们可以独立访问其依赖项,因此可以使用Dictionary>工厂;

总的来说,我将看一下依赖容器。 无论您从事什么工作,都可能只是将其作为一种模式而已,并且已经制作了许多内容,因此无需自己动手制作。 如果要按类型返回对象,则这是一个依赖容器。 另外,我建议通过注入,这样您就不会与容器耦合。 换句话说,将其包装在接口中,然后使用现成的(Unity,MEF等)

public interface IDependencyContainer
{
    T Resolve<T>();
    void Register<T>(T instance);
    void Register<T>(Func<T> instance);
}

暂无
暂无

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

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