是否可以使用工厂方法使用ac#object initializer?

我有一个带有静态工厂方法的类。 我想调用工厂来检索类的实例,然后通过c#object initializer语法进行额外的初始化:

MyClass instance = MyClass.FactoryCreate() { someProperty = someValue; } 

VS

 MyClass instance = MyClass.FactoryCreate(); instance.someProperty = someValue; 

不然。或者您可以接受lambda作为参数,这也可以让您完全控制“创建”过程的哪一部分将被调用。 这样你就可以这样称呼它:

 MyClass instance = MyClass.FactoryCreate(c=> { c.SomeProperty = something; c.AnotherProperty = somethingElse; }); 

创建看起来类似于:

 public static MyClass FactoryCreate(Action initalizer) { MyClass myClass = new MyClass(); //do stuff initializer( myClass ); //do more stuff return myClass; } 

另一种选择是返回构建器(使用隐式转换运算符到MyClass)。 您可以这样称呼:

 MyClass instance = MyClass.FactoryCreate() .WithSomeProperty(something) .WithAnotherProperty(somethingElse); 

检查此构建器

这两个版本都在编译时检查并具有完整的intellisense支持。


第三个选项需要默认构造函数:

 //used like: var data = MyClass.FactoryCreate(() => new Data { Desc = "something", Id = 1 }); //Implemented as: public static MyClass FactoryCreate(Expression> initializer) { var myclass = new MyClass(); ApplyInitializer(myclass, (MemberInitExpression)initializer.Body); return myclass ; } //using this: static void ApplyInitializer(object instance, MemberInitExpression initalizer) { foreach (var bind in initalizer.Bindings.Cast()) { var prop = (PropertyInfo)bind.Member; var value = ((ConstantExpression)bind.Expression).Value; prop.SetValue(instance, value, null); } } 

它是在编译时检查而未检查的中间。 它确实需要一些工作,因为它强制在赋值上不断表达。 我认为其他任何东西都是答案中已有方法的变体。 请记住,您也可以使用正常的作业,考虑是否真的需要这些作业。

您可以使用扩展方法,如下所示:

 namespace Utility.Extensions { public static class Generic { ///  /// Initialize instance. ///  public static T Initialize(this T instance, Action initializer) { initializer(instance); return instance; } } } 

您可以这样称呼它:

 using Utility.Extensions; // ... var result = MyClass.FactoryCreate() .Initialize(x => { x.someProperty = someValue; x.someProperty2 = someValue2; }); 

关于“否”的+1。

这是匿名对象方式的替代方法:

 var instance = MyClass.FactoryCreate( SomeProperty => "Some value", OtherProperty => "Other value"); 

在这种情况下, FactoryCreate()将类似于:

 public static MyClass FactoryCreate(params Func[] initializers) { var result = new MyClass(); foreach (var init in initializers) { var name = init.Method.GetParameters()[0].Name; var value = init(null); typeof(MyClass) .GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.IgnoreCase) .SetValue(result, value, null); } return result; } 

不,对象初始值设定项只能在使用构造函数调用“new”时使用。 一种选择可能是在工厂方法中添加一些额外的args,以便在工厂内创建对象时设置这些值。

 MyClass instance = MyClass.FactoryCreate(int someValue, string otherValue); 

像所有人说的那样,没有。

已经提出了lambda作为论据。
更优雅的方法是接受匿名并根据对象设置属性。 即

 MyClass instance = MyClass.FactoryCreate(new { SomeProperty = someValue, OtherProperty = otherValue }); 

但这会慢得多,因为对象必须反映在所有属性上。

不,那是你只能做’内联’的事情。 所有工厂function都可以为您做的是返回参考。