我正在尝试创建一个抽象类(A),它返回一个自己的通用子项的实例(B)。
我将B的costructor设为内部,在没有我的工厂的情况下创建了一个新的实例,这导致了一个我无法找到解决方案的错误:
'A.B'必须是具有公共无参数的非抽象类型 构造函数,以便在泛型类型中使用它作为参数'T' 方法A.Create()。
C#中有这样的问题的解决方案吗?
namespace C
{
class P
{
static void Main() => Console.WriteLine(A.Create<A.B>().GetType());
}
public abstract class A
{
public class B : A { protected B() { } }
public static T Create<T>() where T : A, new() => new T();
}
}
答案 0 :(得分:5)
public static T Create<T>() where T : A, new()
定义了一个公共方法,声明T
必须具有公共构造函数,因为泛型类型约束new()
。因此,构造函数不能被保护或内部。
将静态工厂方法Create
改为类B
。
class P
{
static void Main() => Console.WriteLine(A.B.Create().GetType());
}
public abstract class A
{
public class B : A
{
private B() { }
public static B Create() => new B();
}
}
更通用的方法是使用工厂代理字典,允许您将构造函数保持为私有。
class P
{
static void Main() => Console.WriteLine(A.Create<A.B>().GetType());
}
public abstract class A
{
private static Dictionary<Type, Func<A>> _factories = new Dictionary<Type, Func<A>> {
[typeof(B)] = () => B.Create(), // Example using factory method.
[typeof(C)] = () => new C() // Example using constructor.
};
public static T Create<T>() where T : A => (T)_factories[typeof(T)]();
public class B : A
{
private B() { }
internal static B Create() => new B();
}
public class C : A
{
internal C() { }
}
}
在现实世界的示例中,您可能希望添加一些错误检查。如果构造函数internal
足以为您提供保护,那么您不需要内部类中的工厂方法(使用类C
显示)。
您也可以公开接口,并保持类(除了一些静态工厂类)完全私有。
还考虑使用依赖注入容器。他们的目标是解决这类问题(以及更多)。
答案 1 :(得分:1)
这是你的班级:
public class B : A { protected B() { } }
构造函数是protected
;因此,只有那些继承B
的类才能调用构造函数。没有其他人。
另一种方法
不确定您是否喜欢这个,但您可以采取的一种方法是创建一个公共抽象类,然后将您的具体类型设为私有。客户端将仅使用抽象接口,但要求您通过方法创建特定的具体类型。如下所示:
public abstract class SomeClass
{
public abstract string DoSomething();
}
public abstract class A
{
private class B : SomeClass
{
public override string DoSomething()
{
return "Something is done in B";
}
}
public static SomeClass CreateB()
{
SomeClass sc = new B();
return sc;
}
}
public static class Program
{
public static void Main()
{
var b = A.CreateB();
Console.WriteLine(b.DoSomething());
}
}
答案 2 :(得分:1)
结束与@Olivier Jacot-Descombes'非常相似的方法。不同之处仅在于A的孩子不在其中:
internal class Program
{
private static void Main()
{
var ab = A.Create<B>();
ab.Foo();
var ac = A.Create<C>();
ac.Foo();
}
}
public abstract class A
{
public virtual void Foo() => Console.WriteLine("A");
public static A Create<T>()
where T : A
{
return Factories[typeof(T)]();
}
private static readonly Dictionary<Type, Func<A>> Factories;
static A()
{
Factories = new Dictionary<Type, Func<A>>();
B.AppendFactory(Factories);
C.AppendFactory(Factories);
}
}
public class B : A
{
private B() => Console.WriteLine("B.ctor()");
public override void Foo() => Console.WriteLine("B");
public static void AppendFactory(Dictionary<Type, Func<A>> factories)
{
factories.TryAdd(typeof(B), () => new B());
}
}
public class C : A
{
private C() => Console.WriteLine("C.ctor()");
public override void Foo() => Console.WriteLine("C");
public static void AppendFactory(Dictionary<Type, Func<A>> factories)
{
factories.TryAdd(typeof(C), () => new C());
}
}