Jas*_*yne 26 c# factory object initializer
我有一个带有静态工厂方法的类.我想调用工厂来检索类的实例,然后通过c#object initializer语法进行额外的初始化:
MyClass instance = MyClass.FactoryCreate()
{
someProperty = someValue;
}
Run Code Online (Sandbox Code Playgroud)
VS
MyClass instance = MyClass.FactoryCreate();
instance.someProperty = someValue;
Run Code Online (Sandbox Code Playgroud)
egl*_*ius 28
不然.或者您可以接受lambda作为参数,这也可以让您完全控制"创建"过程的哪一部分将被调用.这样你就可以这样称呼它:
MyClass instance = MyClass.FactoryCreate(c=>
{
c.SomeProperty = something;
c.AnotherProperty = somethingElse;
});
Run Code Online (Sandbox Code Playgroud)
创建看起来类似于:
public static MyClass FactoryCreate(Action<MyClass> initalizer)
{
MyClass myClass = new MyClass();
//do stuff
initializer( myClass );
//do more stuff
return myClass;
}
Run Code Online (Sandbox Code Playgroud)
另一种选择是返回构建器(使用隐式强制转换运算符到MyClass).您可以这样称呼:
MyClass instance = MyClass.FactoryCreate()
.WithSomeProperty(something)
.WithAnotherProperty(somethingElse);
Run Code Online (Sandbox Code Playgroud)
检查这个构建器
这两个版本都在编译时检查并具有完整的intellisense支持.
第三个选项需要默认构造函数:
//used like:
var data = MyClass.FactoryCreate(() => new Data
{
Desc = "something",
Id = 1
});
//Implemented as:
public static MyClass FactoryCreate(Expression<Func<MyClass>> 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<MemberAssignment>())
{
var prop = (PropertyInfo)bind.Member;
var value = ((ConstantExpression)bind.Expression).Value;
prop.SetValue(instance, value, null);
}
}
Run Code Online (Sandbox Code Playgroud)
它是在编译时检查而未检查的中间.它确实需要一些工作,因为它强制在赋值上不断表达.我认为其他任何东西都是答案中已有方法的变体.请记住,您也可以使用正常的作业,考虑是否真的需要这些作业.
您可以使用如下扩展方法:
namespace Utility.Extensions
{
public static class Generic
{
/// <summary>
/// Initialize instance.
/// </summary>
public static T Initialize<T>(this T instance, Action<T> initializer)
{
initializer(instance);
return instance;
}
}
}
Run Code Online (Sandbox Code Playgroud)
您可以这样称呼它:
using Utility.Extensions;
// ...
var result = MyClass.FactoryCreate()
.Initialize(x =>
{
x.someProperty = someValue;
x.someProperty2 = someValue2;
});
Run Code Online (Sandbox Code Playgroud)
是的。您可以通过以下技巧对已创建的实例使用对象初始值设定项。您应该创建一个简单的对象包装器:
public struct ObjectIniter<TObject>
{
public ObjectIniter(TObject obj)
{
Obj = obj;
}
public TObject Obj { get; }
}
Run Code Online (Sandbox Code Playgroud)
现在你可以像这样使用它来初始化你的对象:
new ObjectIniter<MyClass>(existingInstance)
{
Obj =
{
//Object initializer of MyClass:
Property1 = value1,
Property2 = value2,
//...
}
};
Run Code Online (Sandbox Code Playgroud)
PS dotnet存储库中的相关讨论: https ://github.com/dotnet/csharplang/issues/803
| 归档时间: |
|
| 查看次数: |
4632 次 |
| 最近记录: |