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

编辑

我添加了第二个带有名称参数的构造函数。我要强制初始化名称,删除第一个无参数构造函数。

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 回答