使通用对象实例化更通用

时间:2012-08-25 19:43:21

标签: c# c#-4.0 generics

我有这段代码以通用的方式创建新对象:

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

我不喜欢的是我需要传递'通用符号'&lt; T&gt;为每个创建调用。毕竟我创建了一个我已经提到的对象......

此当前功能背后的代码是:

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");

谢谢!

5 个答案:

答案 0 :(得分: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方法的类型。

答案 1 :(得分: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; }
  }

编辑:在之后更新了代码我在本地环境中测试了它。它现在有效。

答案 2 :(得分: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参数的构造函数。我想强制初始化名称,删除第一个无参数构造函数。

var user = new User("xy");

答案 3 :(得分:1)

你这样做是错误的。而不是摆脱泛型论点,摆脱(不必要)说User.。代替:

CreateBase.Create<User>(...)

不再有裁员。

除此之外,通过派生类调用基类的静态成员是一种反模式。

答案 4 :(得分:0)

如果你真的对这个sintax感到不舒服(老实说,我不会在这里看到太多问题)

您可以执行以下操作:

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");