Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 基于类型的工厂或是_C#_Factory - Fatal编程技术网

C# 基于类型的工厂或是

C# 基于类型的工厂或是,c#,factory,C#,Factory,在下面的代码中,我希望返回基于另一个类的类型的派生类,这是一种更优雅的方式 if (option_ is Rectangle) { modelInputs = new Foo(); } else if (option_ is Circle) { modelInputs = new Bar();

在下面的代码中,我希望返回基于另一个类的类型的派生类,这是一种更优雅的方式

            if (option_ is Rectangle)
            {
                modelInputs = new Foo();
            }
            else if (option_ is Circle)
            {
                modelInputs = new Bar();
            }
            else if (option_ is Triangle)
            {
                modelInputs = new Bar2();
            }

如果允许,您可以将一个类型与“option_”关联,然后只创建一个实例。

让矩形、圆形和三角形实现IHasModelInput:

interface IHasModelInput
{
    IModelInput GetModelInput();
}
那你就可以了

IModelInput modelInputs = option_.GetModelInput();
我的意见是:你的“不雅”方式很好。它简单易读,很好用

让矩形、圆形和三角形通过IHasModelInput实现必要的工厂函数是可行的,但这需要付出设计代价:现在您已经将这组类与IModelInput组类(Foo、Bar和Bar2)耦合起来。他们可能在两个完全不同的图书馆,也许他们不应该互相了解

下面是一个更复杂的方法。它使您能够在运行时配置工厂逻辑

    public static class FactoryMethod<T>  where T : IModelInput, new()
    {
        public static IModelInput Create()
        {
            return new T();
        }
    }

    delegate IModelInput ModelInputCreateFunction();

    IModelInput CreateIModelInput(object item)
    {

        Dictionary<Type, ModelInputCreateFunction> factory = new Dictionary<Type, ModelInputCreateFunction>();


        factory.Add(typeof(Rectangle), FactoryMethod<Foo>.Create);
        factory.Add(typeof(Circle),    FactoryMethod<Bar>.Create);
        // Add more type mappings here




        IModelInput modelInput;
        foreach (Type t in factory.Keys)
        {
            if ( item.GetType().IsSubclassOf(t) || item.GetType().Equals(t))
            {
                modelInput = factory[t].Invoke();
                break;
            }
        }
        return modelInput;
    }
公共静态类FactoryMethod,其中T:imodeInput,new()
{
公共静态输入创建()
{
返回新的T();
}
}
委托IModelInput ModelInputCreateFunction();
IModelInput CreateIModelInput(对象项)
{
字典工厂=新字典();
Add(typeof(矩形),FactoryMethod.Create);
Add(typeof(Circle),FactoryMethod.Create);
//在此处添加更多类型映射
IModelInput模型输入;
foreach(工厂中的t型钥匙)
{
if(item.GetType().IsSubclassOf(t)| | item.GetType().Equals(t))
{
modelInput=工厂[t]。调用();
打破
}
}
返回模型输入;
}

然后问一个问题:你更愿意读哪一个?

你可以将输入和输出放在哈希表中,或者将创建每个类的类型存储在创建的每个类中,然后使用Activator.CreateInstance执行factoryin':

Hashtable ht = new Hashtable();
ht.Add(typeof(Rectangle), typeof(Bar));
ht.Add(typeof(Square), typeof(Bar2));

modelInputs = Activator.CreateInstance(ht[option.GetType()]);

无论哪种方式,Activator.CreateInstance都是一种让工厂在.NET中工作的非常酷的方式。享受并明智地使用我给你的力量,儿子。

我通常使用这样的工厂方法当我想在运行时将字符串转换为类型时,我使用一个字典将字符串映射为类型

比如最近的一个项目:

public class TaskFactory
{
    private Dictionary<String, Type> _taskTypes = new Dictionary<String, Type>();

    public TaskFactory()
    {
        // Preload the Task Types into a dictionary so we can look them up later
        foreach (Type type in typeof(TaskFactory).Assembly.GetTypes())
        {
            if (type.IsSubclassOf(typeof(CCTask)))
            {
                _taskTypes[type.Name.ToLower()] = type;
            }
        }
    }

    public CCTask CreateTask(XmlElement task)
    {
        if (task != null)
        {
            string taskName = task.Name;
            taskName =  taskName.ToLower() + "task";

            // If the Type information is in our Dictionary, instantiate a new instance of that task
            Type taskType;
            if (_taskTypes.TryGetValue(taskName, out taskType))
            {
                return (CCTask)Activator.CreateInstance(taskType, task);
            }
            else
            {
                throw new ArgumentException("Unrecognized Task:" + task.Name);
            }                               
        }
        else
        {
            return null;
        }
    }
}
公共类任务工厂
{
私有字典_taskTypes=新字典();
公共任务工厂()
{
//将任务类型预加载到字典中,以便我们以后可以查找它们
foreach(typeof(TaskFactory).Assembly.GetTypes()中的类型)
{
if(类型IsSubclassOf(类型CCTask)))
{
_taskTypes[type.Name.ToLower()]=type;
}
}
}
公共CCTask CreateTask(XmlElement任务)
{
如果(任务!=null)
{
字符串taskName=task.Name;
taskName=taskName.ToLower()+“任务”;
//如果类型信息在我们的字典中,请实例化该任务的新实例
任务类型;
if(_taskTypes.TryGetValue(taskName,out taskType))
{
return(CCTask)Activator.CreateInstance(taskType,task);
}
其他的
{
抛出新ArgumentException(“无法识别的任务:+Task.Name”);
}                               
}
其他的
{
返回null;
}
}
}

我同意将矩形、圆形等一组类与模型输入耦合起来不是很好。在这些情况下,我通常只是从输入类型的字典到输出类型,并使用Activator.CreateInstance。