我的代码中有一个简单的Factory实现。我的目标是让构造的对象保留对创建它们的工厂的引用,所以我将它们连接起来类似于:
public class Factory {
public T CreateObject<T>() where T : Foo, new()
{
return new T() {
parent = this
};
}
}
public class Foo {
internal Factory parent;
internal Foo() { }
}
这可以读取,但我一直在想我可能想要parent
变量,这样一旦它被工厂设置就无法更改。但是,如果我将其声明为internal readonly Factory parent;
,则工厂不能再在构造时设置它的值。
我通常通过提供参数化构造函数来解决这个问题,但这会破坏通用实现,因为AFAIK where T : new()
意味着无参数构造函数。
我可能只是错过了一些我的C#chops的齿轮,但是实现这样的东西最好的方法是什么? (或者最好放弃readonly
并相信代码不会以不安全的方式修改parent
--- NullReferenceException
会浮现在脑海中...... )
答案 0 :(得分:4)
您可以使用反射来设置字段,无论readonly
修饰符如何,这都可以使用:
public class Factory
{
public T CreateObject<T>() where T : Foo, new()
{
T t = new T();
t.GetType()
.GetField("parent", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(t, this);
return t;
}
}
答案 1 :(得分:4)
我认为你不能准确获得你想要的东西,但你可以制作一个只可分配一次的属性,让工厂覆盖它。但我想用户总是可以强制覆盖new CreatingFactory
,但我认为这很难,至少清楚地表明了你的意图。
您可以执行以下操作。
class Foo
{
private Factory factory;
public Factory CreatingFactory
{
get { return factory; }
set
{
if (factory != null)
{
throw new InvalidOperationException("the factory can only be set once");
}
factory = value;
}
}
}
class Factory
{
public T Create<T>()
where T : Foo, new()
{
T t = new T()
{
CreatingFactory = this
};
return t;
}
}
创建它之后,我搜索并找到了一个可能比我更好的答案:Is there a way of setting a property once only in C#
答案 2 :(得分:0)
我不确定这是否正是您想要的,但我想出了一种方法,用Func
替换您的泛型类型参数,该方法显示如何构造Foo
对象并允许您可以在构造函数中设置父级。
public class Factory {
private Func<Factory, Foo> creator;
public Factory(Func<Factory, Foo> creator) {
this.creator = creator;
}
public Foo CreateObject()
{
return this.creator(this);
}
}
public class Foo {
internal readonly Factory parent;
internal Foo(Factory parent) {
this.parent = parent;
}
}
然后
public void Main() {
Factory myfactory = new Factory(fact => new Foo(fact));
Foo myfoo = myfactory.CreateObject();
}