【问题标题】:Factory method that returns generic instance返回通用实例的工厂方法
【发布时间】:2016-12-24 15:51:01
【问题描述】:

我有一个带有虚拟方法的基础服务类,它设置对象的属性并返回该对象。
然后我还有一项从基础服务派生的服务,并且还覆盖了基础方法。在覆盖方法中,派生服务执行base.DowWork() 设置公共属性,然后还设置附加属性。
所以基于文章herehere 我能够使用泛型来做到这一点。

    public interface IResult
    {
    }

    public class BaseResult : IResult
    {
        public string CommonProperties { get; set; }
    }

    public class AdditionalResult : BaseResult
    {
        public string AdditionalProperties { get; set; }
    }

    public interface IService<T> where T : IResult
    {
        T DoWork();
    }

    public class BaseService<T> : IService<T> where T : BaseResult, new()
    {
        public virtual T DoWork()
        {
            var t = new T();

            t.CommonProperties = "Some Value";

            return t;
        }
    }
    public class AdditionalService : BaseService<AdditionalResult>
    {
        public override AdditionalResult DoWork()
        {
            var addtionalResult = base.DoWork();

            addtionalResult.CommonProperties = "Override value that was set by BaseService";
            addtionalResult.AdditionalProperties = "Set additional properties";

            return addtionalResult;
        }
    }

到目前为止一切顺利
现在我想创建一个工厂方法,该方法将返回基于某种类型的服务实例。应用程序将使用工厂获取服务实例并调用 DoWork(),如下所示

class Program
    {
        static void Main()
        {
            var factory = new MyFactory();
            var service = factory.GetService(0);
            var iresult = service.DoWork();

            // do something here with IResult              
        }
    }

下面是工厂方法

public class MyFactory
{
    public IService<IResult> GetService(int someType)
    {
        if (someType == 0)
        {
            return (IService<IResult>)new BaseService<BaseResult>();
        }

        if (someType == 1)
        {
            return (IService<IResult>)new AdditionalService();
        }

        // note I may have more types and services here. But for simplicity  i am using only 2

        throw new NotSupportedException();
    }
}

但是我无法弄清楚这个工厂方法的签名应该是什么?根据建议here 我正在投射服务实例,但在执行应用程序时出现运行时异常

无法转换类型的对象 'BaseService 1[BaseResult]' 到 输入“IService 1[IResult]”

如果我不在工厂中转换服务实例,那么我会得到编译时错误

无法将类型“BaseService”隐式转换为 '我服务'。存在显式转换(您是否缺少 演员?)

【问题讨论】:

    标签: c# generics


    【解决方案1】:

    请参阅 SO 问题 Understanding Covariant and Contravariant interfaces in C#

    您想使用协方差(out 关键字)。如果您将其添加到您的 IService 接口泛型类型,它会按预期工作。

    public interface IService<out T> where T : IResult
    

    我知道 SO 不喜欢发布链接,但我写不出比 answered in that question 更多或更好的东西了。

    【讨论】:

    • 我在上面提供的链接之一http://stackoverflow.com/questions/1723648/how-to-inherit-method-but-with-different-return-typeNo, the feature you mentioned is called return type covariance. It's not supported in C#.
    • @LP13 - 在您的链接示例中,它不起作用,因为没有返回通用类型。在这种情况下,返回类型应该实现IResult,这没关系,任何实现 IService 的类型都应该有一个返回实现 IResult 的类型的成员。
    • 感谢工作。很抱歉重新发布已回答的问题
    • @LP13 - 不用担心!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多