通用工厂类 [英] Generic Factory Class

查看:69
本文介绍了通用工厂类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





tl:dr部分:

这个这是我第一个问题,可以在这里找到: c#接口和通用类型 [ ^ ]



我在蓝天工作计划改善我们的核心工厂类。我的最终目标是在工作类之间共享重复的代码和方法,并使工厂类的使用更加直观。



我们当前必须将返回类型和worker类型传递给工厂,然后工厂将使用反射来调用worker方法。我们最终得到了一个工厂类,它具有工作者可能拥有的每种可能方法的方法(包括一些仅针对1个工人的方法> _<)。



我希望有一个工厂类可以作为或返回一个特定的工人类,这样我们就可以通过智能分辨出哪些方法可用,而不必自己查看工人类。



我必须要考虑的一个限制是解决方案的每一层都必须尽可能隔离,但只有业务逻辑层需要工厂。



我非常有兴趣在我的工厂使用仿制药,希望可以处理任何铸件。我确信我过去做过类似的事情,但我不再能够访问该代码了。



工厂的当前实施

反思方面是现有的。当前的Factory方法例如如下所示:

  public   partial   class 工厂< T> 其中 T: new ()
{
公开 静态 U获取< U>(对象项目)
{
T instance = Activator.CreateInstance< T>();
object [] parameters = {item};
return (U)instance.GetType()。GetMethod( 获取)。调用(实例,参数);
}
}





也许这是最好的方式吗?



一些具体问题:



是否可以确定类型返回类型的工厂,还是我必须施放它?

  //  我可以这样做吗 
会员m = Factory.Get(ID); // 其中Factory< type>知道该类型是会员?
// 或者它必须是其中之一:
m =工厂<会员> .Get();
m = Factory.Get< Member>();



也许这不应该是我的方法。我正在寻找尽可能简单直观地使用核心层的最佳方法。



谢谢

解决方案

我不确定我到底知道你要做什么,所以这段代码可能没什么用,但我会捅一下。



首先,如果您的泛型类型约束确保类型T具有无参数构造函数,则应使用新的T()而不是Activator.CreateInstance()。



其次,看起来您正在尝试实例化类型T然后返回该类型的属性。这对我来说似乎是一个奇怪的用例,因为T的实例基本上被丢弃了,但假设你想要做的就是这样做:



  public   partial  工厂< T> 其中 T: new ()
{
公开 静态 U获取< U>(Func< T,U>选择器)
{
var instance = new T();
return selector(instance);
}
}

// 使用如下:
工厂<会员> .Get(m = > m.FirstName);





再次,我不确定这是你要求的,但它似乎是。如果你想确保Get方法上的特定子类或接口类型在类型U上具有泛型类型约束,你可以更进一步。例如,在U:IWorker的地方。



这种方法为您提供了一种智能感知方法,用于选择工厂类型的成员,但正如我所说,它在当前状态下似乎没有用。





------------------基于对问题的仔细审查更新------------- ----



我认为以下代码可能更符合您的要求。如果是,我建议您根据自己使用的内容考虑,如果您尝试实例化并返回非数据对象,请切换到Autofac或StructureMap等控制框架的依赖注入/反转。如果您尝试按需从数据存储区返回数据,请访问EntityFramework或NHibernate等数据框架。



然而......这是我的代码,我没有实际检查是否会编译:



  //  < span class =code-comment>类型不可知工厂接口(用于在字典或列表中存储各种类型的实例) 
public interface IFactory
{
object 获取( int entityId);
}

// 通用工厂界面
public interface IFactory< T> :IFactory
{
T Get( int entityId);
}

// 与类型无关的工厂类型的抽象基类和通用接口
public abstract class 工厂< T> :IFactory< T>
{
abstract T Get( int entityId);

object IFactory.Get( int entityId){
< span class =code-keyword> return 获取(entityId);
}
}

// 了解a的专业工厂特定类型
public class MemberFactory:Factory< Member>
{
public 覆盖成员获取( int entityId){
return new 成员{MemberId = entityId, FirstName = John,LastName = Doe};
}
}

// 构造值的通用工厂类型为T并返回
public class GenericFactory< T> :工厂< T>
{
private Func< int,T>构造函数;
public GenericFactory(Func< int,T> constructor)
{
this .constructor = constructor;
}

public 覆盖 T Get( int entityId){
return 构造函数(entityId);
}
}

// 非通用静态工厂类它充当您将使用的不同工厂实例的注册表。
public static class 工厂
{
私有 static ConcurrentDictionary< Type,IFactory> TypeFactories = new ConcurrentDictionary< Type,IFactory>();

public static void RegisterFactory< T>(IFactory< T> factory)
{
TypeFactories.AddOrUpdate( typeof (T),t = > factory,(t,f)= > factory);
}

public static T Get< T>(< span class =code-keyword> int entityId)
{
var type = typeof运算(T);
IFactory untypedFactory
if (!TypeFactories.TryGetValue(type, out untypedFactory) )
{
throw new FactoryNotFoundException(type);
}

var factory = untypedFactory as IFactory< T> ;
if (factory == null
{
throw new StopMessingWithMyPrivateStaticDictionaryException();
}

return factory.Get(entityId);
}
}

// 应用程序设置:
Factory.RegisterFactory( new MemberFactory());
Factory.RegisterFactory( new GenericFactory< Product>(id = > new Product {ProductId = id}));
Factory.RegisterFactory( new GenericFactory< FooBar>(id = > new FooBar(id));

// 用法:
var member = Factory.Get< Member>( 1234 );


Hi,

The tl:dr part:
This is a second question following my first that can be found here: c# Interfaces and Generic Types[^]

I am working on a "blue sky" project to improve our core factory classes. My end goal is to have duplicated code and methods shared between the worker classes and to make the use of the factory classes more intuitive.

We currently have to pass the return type and the worker type to the factory which will then use reflection to call the worker method. We end up with a factory class that has a method for every possible method that the worker might have (including some that are specific to only 1 worker >_< ).

I would like to have a factory class that acted as, or returned, a specific worker class so we could tell what methods are available through intellisence and not have to look through the worker class ourselves.

A restriction I have to bare in mind is that each layer of the solution has to be as isolated as possible, but only the business logic layer requires a factory.

I am very interested in using generics with my factory that could hopefully take care of any casting. I'm sure I have done something similar in the past but I no longer have access to that code.

The Current implementation of the factory
The Reflection aspect is what is currently in place. The current Factory method Get for example looks like this:

public partial class Factory<T> where T : new()
{
    public static U Get<U>(object item)
    {
        T instance = Activator.CreateInstance<T>();
        object[] parameters = { item };
        return (U)instance.GetType().GetMethod("Get").Invoke(instance, parameters);
    }
}



Maybe that is the best way after all?

Some specific questions:

Is is possible to determine the type of factory from the return type, or do I have to cast it?

//Can I do this
Member m = Factory.Get(ID); // where Factory<type> knows that the type is Member?
//Or does it have to be one of these:
m = Factory<Member>.Get();
m = Factory.Get<Member>(); 


Maybe this shouldn't be my approach. I'm looking for the best way to make the use of our core layers as easy and as intuitive as possible.

Thanks

解决方案

I'm not sure I understand exactly what you're trying to do so this code may not be helpful but I'll take a stab at it.

First, if your generic type constraint ensures that type T has a parameterless constructor you should use new T() instead of Activator.CreateInstance().

Secondly, it seems like you're trying to instantiate type T and then return an property of that type. That seems like an odd use-case to me as the instance of T is then essentially discarded, but assuming that is what you're wanting to do you could do so like this:

public partial class Factory<T> where T : new()
{
    public static U Get<U>(Func<T, U> selector)
    {
        var instance = new T();
        return selector(instance);
    }
}

// use like this:
Factory<Member>.Get(m => m.FirstName);



Again, I'm not sure that is what you're asking for but it seems like it is. You could go further if you want to ensure a specific subclass or interface type on the Get method with a generic type constraint on type U. For instance where U : IWorker.

This approach gives you a single method with intellisense for selecting the members of the factory type, but as I've said it doesn't seem very useful in its current state.


------------------ Update based on closer review of the question -----------------

I think that the following code might be more what you're looking for. If it is I'd suggest that you consider, based on what you're using it for, either switching to a Dependency Injection / Inversion of control framework like Autofac or StructureMap if you're trying to instantiate and return non-data objects or to a data framework like EntityFramework or NHibernate if you are trying to return data from a datastore on demand.

Nevertheless... here is my code which I've not actually checked to see if it will compile:

// type agnostic factory interface (useful for storing instances of various types in a dictionary or list)
public interface IFactory
{
    object Get(int entityId);
}

// generic factory interface
public interface IFactory<T> : IFactory
{
    T Get(int entityId);
}

// abstract base class for factory types that marries the type agnostic and generic interfaces
public abstract class Factory<T> : IFactory<T>
{
    abstract T Get(int entityId);

    object IFactory.Get(int entityId) {
        return Get(entityId);
    }
}

// specialized factory that knows about a specific type
public class MemberFactory : Factory<Member>
{
    public override Member Get(int entityId) {
        return new Member { MemberId = entityId, FirstName = "John", LastName = "Doe" };
    }
}

// generic factory that constructs a value of type T and returns it
public class GenericFactory<T> : Factory<T>
{
    private Func<int, T> constructor;
    public GenericFactory(Func<int, T> constructor)
    {
        this.constructor = constructor;
    }

    public override T Get(int entityId) {
        return constructor(entityId);
    }
}

// non-generic static Factory class which acts as a registry for the different factory instances you will use.
public static class Factory
{
    private static ConcurrentDictionary<Type, IFactory> TypeFactories = new ConcurrentDictionary<Type, IFactory>();

    public static void RegisterFactory<T>(IFactory<T> factory)
    {
        TypeFactories.AddOrUpdate(typeof(T), t => factory, (t, f) => factory);
    }

    public static T Get<T>(int entityId)
    {
        var type = typeof(T);
        IFactory untypedFactory
        if (!TypeFactories.TryGetValue(type, out untypedFactory))
        {
            throw new FactoryNotFoundException(type);
        }

        var factory = untypedFactory as IFactory<T>;
        if (factory == null)
        {
            throw new StopMessingWithMyPrivateStaticDictionaryException();
        }

        return factory.Get(entityId);
    }
}

// application setup:
Factory.RegisterFactory(new MemberFactory());
Factory.RegisterFactory(new GenericFactory<Product>(id => new Product { ProductId = id }));
Factory.RegisterFactory(new GenericFactory<FooBar>(id => new FooBar(id));

// usage:
var member = Factory.Get<Member>(1234);


这篇关于通用工厂类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆