4

別のクラスの型に基づいて派生クラスを返したい場合に、以下のコードを使用するよりエレガントな方法は何ですか。

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

5 に答える 5

8

Rectangle、Circle、および Triangle に IHasModelInput を実装させます。

interface IHasModelInput
{
    IModelInput GetModelInput();
}

それからあなたはすることができます

IModelInput modelInputs = option_.GetModelInput();
于 2008-10-28T02:57:41.200 に答える
3

私の意見: あなたの「洗練されていない」方法は問題ありません。シンプルで読みやすく、仕事をします。

Rectangle、Circle、および Triangle にIHasModelInputを介して必要なファクトリ関数を実装させることは機能しますが、設計コストがかかります。これで、このクラスのセットを IModelInput クラスのセット (Foo、Bar、および Bar2) と結合しました。それらは 2 つの完全に異なるライブラリに存在する可能性があり、お互いを認識すべきではない可能性があります。

より複雑な方法を以下に示します。実行時にファクトリ ロジックを構成できるという利点があります。

    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;
    }

しかし、次の質問をしてください。どちらを読みたいですか?

于 2008-10-28T03:49:07.570 に答える
1

入力と出力を Hashtable に入れるか、作成した各クラス内に各クラスを作成する型を格納してから、Activator.CreateInstance を使用してファクトリを実行できます。

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 で動作させる非常に優れた方法です。楽しんで、私があなたに与えた力を賢く使ってください、息子よ。

于 2008-10-28T04:02:12.160 に答える
0

実行時に文字列を型に変換したい場合は、通常、このようなファクトリ メソッドを使用します。文字列を型にマップするディクショナリを使用します。

最近のプロジェクトからこのように:

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;
        }
    }
}
于 2008-10-28T04:05:55.680 に答える
0

可能であれば、タイプを「option_」に関連付けてから、そのインスタンスを作成するだけです。

于 2008-10-28T02:56:05.930 に答える