简体   繁体   English

来自通用接口的工厂模式

[英]Factory pattern from generic interface

I have generic interface IProcessor<T, TU> and 2 implementations of it: 我有通用接口IProcessor<T, TU>及其2个实现:

StandartDocumentProcessor and ModDocuemntProcessor . StandartDocumentProcessorModDocuemntProcessor

I'm going to use Factory pattern (or smth similiar) to instantiate variable currentProcessor . 我将使用Factory模式(或类似的模式)实例化变量currentProcessor

IProcessor<T, TU> currentProcessor = Factory.Create(argument) . IProcessor<T, TU> currentProcessor = Factory.Create(argument)

Then I'm going to call method currentProcessor.ProcessFrom() and currentProcessor.ProcessTo() . 然后,我将调用方法currentProcessor.ProcessFrom()currentProcessor.ProcessTo()

1st problem : it's impossible to have IProcessor<T,TU> or IProcessor types for currentProcessor, as CLR doesn't allow this and insists to have specific type for my variable. 第一个问题 :currentProcessor不能具有IProcessor<T,TU>IProcessor类型,因为CLR不允许这样做,并且坚持为变量指定特定类型。

2nd problem : I surfed over the internet and found ugly solutions with Reflection or Activator.CreateInstance() which have familiar issues with downgrading performance. 第二个问题 :我上网冲浪,发现使用ReflectionActivator.CreateInstance()丑陋解决方案性能降低有熟悉的问题。

Please advice, is it possible to avoid: reflection, casting to object or using dynamic . 请注意,是否可以避免:反射,投射到object或使用dynamic

UPD : IProcessor.cs UPDIProcessor.cs

public interface IProcessor<T, TU> where T : DocumentValidation
    {
        HtmlContent RetrieveDocument(SearchItem item);

        bool ValidateObject(T obj);

        T ProcessFrom(HtmlContent content);

        TU ProcessTo(T source);

        bool SaveTo(TU target, T source);

    } 

First implementation of IProcessor - StandardDocumentProcessor.cs 首先实施的IProcessor - StandardDocumentProcessor.cs

class StandardDocumentProcessor : IProcessor<Document, XmlDocument>
    {
        public HtmlContent RetrieveDocument(SearchItem item)
        {
            throw new NotImplementedException();
        }

        public bool ValidateObject(Document obj)
        {
            throw new NotImplementedException();
        }

        public Document ProcessFrom(HtmlContent content)
        {
            throw new NotImplementedException();
        }

        public XmlDocument ProcessTo(Document source)
        {
            throw new NotImplementedException();
        }

        public bool SaveTo(XmlDocument target, Document source)
        {
            throw new NotImplementedException();
        }
    }

Second implementation of IProcessor - ModDocumentProcessor.cs IProcessor第二种实现ModDocumentProcessor.cs

public class ModDocumentProcessor : IProcessor<ModDocument, XmlDocument>
    {
        public HtmlContent RetrieveDocument(SearchItem item)
        {
            throw new NotImplementedException();
        }

        public bool ValidateObject(ModDocument obj)
        {
            throw new NotImplementedException();
        }

        public ModDocument ProcessFrom(HtmlContent content)
        {
            throw new NotImplementedException();
        }

        public XmlDocument ProcessTo(ModDocument source)
        {
            throw new NotImplementedException();
        }

        public bool SaveTo(XmlDocument target, ModDocument source)
        {
            throw new NotImplementedException();
        }
    }

and now I'm going to create factory pattern to instantiate IProcessor<T, TU> with some specific class. 现在,我将创建工厂模式以使用某些特定的类实例化IProcessor<T, TU>

????? currentProcessor = Factory.Create(input_argument_which_allows_to_define_concrete_implementation_of_IProcessor)

That's no matter to display realization of Create method here. 这与在此处显示Create方法的实现无关。 I'm kindly asking about just returning type of Create method . 我问的只是返回Create方法的类型

Since C# 4.0 you can simple declare your factory method as dynamic and it will work: C# 4.0您可以简单地将工厂方法声明为动态方法,它将起作用:

public static dynamic Create(string at) {
   if (condition)
     return new StandardDocumentProcessor();
   else
     return new ModDocumentProcessor();
}

Invocation: 调用:

dynamic m = Create("mod");

Of course, this is like cheating because by using dynamic you'll loose type safety (risking runtime exceptions) and it'll decrease performance. 当然,这就像作弊一样,因为通过dynamic使用,您将失去类型安全性(增加运行时异常),并且会降低性能。

If have no idea about your app domain, but if this aspect is import for you, I would change some things and try generic out parameters. 如果没有你的应用程序域的想法,但如果这方面是导入你的,我会改变一些事情,并尝试仿制out的参数。

public interface IProcessor<out T, out TU> where T : DocumentValidation {
    HtmlContent RetrieveDocument(SearchItem item);
    bool ValidateObject(DocumentValidation obj);
    T ProcessFrom(HtmlContent content);
    TU ProcessTo(DocumentValidation source);
}

Factory: 厂:

public static IProcessor<DocumentValidation, ProcessResult> Create(string at) {
  if (condition(at))
    return new StandardDocumentProcessor();
  else
    return new ModDocumentProcessor();
  }

Note that I removed the SaveTo method because it does not fit into this pattern. 请注意,我删除了SaveTo方法,因为它不适合此模式。 Move it to another interface if you require it anyway. 仍然需要时将其移动到另一个界面。 ProcessResult is a base class / interface for XmlDocument . ProcessResultXmlDocument的基类/接口。

Just another note: everything would be simpler if you wouldn't use generics at all and work with inheritance / base classes. 还要注意一点:如果您根本不使用泛型并使用继承/基类,那么一切都会变得更加简单。 The factory pattern is commonly used to hide and encapsulate implementation details and types, including some generic parameters. 工厂模式通常用于隐藏和封装实现细节和类型,包括一些通用参数。 If you want to get type information out of your factory, perhaps it isn't the best idea to use a factory. 如果要从工厂获取类型信息,使用工厂不是最好的主意。

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

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