2

一般的な方法で新しいオブジェクトを作成するための次のコードがあります。

var user = User.Create<User>(c => c.Name = "321X");

私が気に入らないのは、作成呼び出しごとに「一般的な表記法」 <T> を渡す必要があるという事実です。結局、私はすでに参照しているオブジェクトを作成します...

この現在の機能の背後にあるコードは次のとおりです。

public class User : CreateBase
{
    public string Name { get; set; }
}

public abstract class CreateBase
{
    public DateTime CreateDate { get; set; }
    public Guid Guid { get; set; }

    public static T Create<T>(Action<T> init) where T : CreateBase, new()
    {
        T obj = new T();
        obj.Guid = Guid.NewGuid();
        obj.DateTime = DateTime.Now;
        init(obj);
        return obj;
    }
}

私のコードをこれにリファクタリングしてオブジェクトを作成することは可能ですか (そしてどのように)?

var user = User.Create(c => c.Name = "321X");

ありがとう!

4

5 に答える 5

2

あなたはそれほど遠くありませんでした。この変更を試してください:

  public abstract class CreateBase<T> where T : CreateBase<T> , new()
  {
    public DateTime CreateDate { get; set; }
    public Guid Guid { get; set; }

    public static T Create(Action<T> init)
    {
      T obj = new T();
      obj.Guid = Guid.NewGuid();
      obj.CreateDate = DateTime.Now;
      init(obj);
      return obj;
    }
  }

  public class User : CreateBase<User>
  {
    public string Name { get; set; }
  }

編集:ローカル環境でテストした、コードを更新しました。それは今動作します。

于 2012-08-25T19:50:32.503 に答える
2

クラス レベルでジェネリック引数を定義します。

public abstract class CreateBase<T> where T : CreateBase<T> , new()
{
    public static T Create(Action<T> init) 
    {
        //...
    }
}

public class User : CreateBase<User>
{
    public string Name { get; set; }
}

それからあなたは書くことができますvar user = User.Create(c => c.Name = "321X");

Createそうしないと、型引数を指定しないと、コンパイラはメソッドの型を推測できません。

于 2012-08-25T19:49:51.217 に答える
1

より良いアプローチは、基本クラスのコンストラクターにこの機能を含めることです (私はそれを ModelBase と呼びます)。

public abstract class ModelBase
{
    public DateTime CreateDate { get; private set; }
    public Guid Guid { get; private set; }

    public ModelBase()
    {
        Guid = Guid.NewGuid();
        DateTime = DateTime.Now;
    }
}

public User : ModelBase
{
    public User()
        : base()
    {
    }

    public User(string name)
        : base()
    {
        Name = name
    }

    public string Name { get; set; } 
}

標準的な方法でユーザーを作成すると、Guid と日付が自動的に初期化されます

var user = new User { Name = "xy };

編集

name パラメーターを持つ 2 つ目のコンストラクターを追加しました。名前の初期化を強制したい場合は、最初のパラメーターなしのコンストラクターを削除します。

var user = new User("xy");
于 2012-08-25T19:50:27.197 に答える
1

あなたはそれを間違った方法でやっています。一般的な引数を取り除く代わりに、(不必要に) と言うことを取り除きますUser.。その代わり:

CreateBase.Create<User>(...)

もう冗長性はありません。

それに加えて、派生クラスを介して基本クラスの静的メンバーを呼び出すことはアンチパターンです。

于 2012-08-25T19:51:35.520 に答える
0

あなたがそのシンタックスに本当に不快感を覚えるなら(正直なところ、ここではあまり問題はないと思います)

次のことができます。

public class User : CreateBase
{
    public string Name { get; set; }

    public static User Create(Action<User> a)
    {
        return Create<User>(a); //CALL BASE CLASS GENERIC FUNCTION
    }
}

あなたがそれをしたい方法でそれを呼び出すことができた後:

var user = User.Create(c => c.Name = "321X");

于 2012-08-25T19:50:09.000 に答える