C# 约束参数,新()
有没有办法将解析方法移动到抽象类中?我尝试了多种方法(底部的链接),但我仍然遇到了一个或另一个障碍C# 约束参数,新(),c#,oop,generics,inheritance,abstract-class,C#,Oop,Generics,Inheritance,Abstract Class,有没有办法将解析方法移动到抽象类中?我尝试了多种方法(底部的链接),但我仍然遇到了一个或另一个障碍 公共类animalentyId:EntityId 提前感谢否,您不能编写模板约束,例如new(string),而只需编写new()。您必须利用反射使其工作: public abstract class EntityId<TEntityId> where TEntityId : EntityId<TEntityId> { private readonl
公共类animalentyId:EntityId
提前感谢否,您不能编写模板约束,例如new(string)
,而只需编写new()
。您必须利用反射使其工作:
public abstract class EntityId<TEntityId>
where TEntityId : EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
public static TEntityId Parse(string value)
{
return (TEntityId)Activator.CreateInstance(typeof(TEntityId), new object[] { value });
}
}
公共抽象类EntityId
其中TEntityId:EntityId
{
私有只读系统。Guid值;
受保护的EntityId(字符串值)
{
this.value=System.Guid.Parse(值);
}
受保护的EntityId()
{
this.value=System.Guid.NewGuid();
}
公共静态TEntityId解析(字符串值)
{
return(TEntityId)Activator.CreateInstance(typeof(TEntityId),新对象[]{value});
}
}
假设您使构造函数可访问(而不是当前的私有构造函数)。注意约束where TEntityId:EntityId
——这将确保我们只返回EntityId
的子类,如果您不介意使用反射,可以将Parse
移动到抽象类型中,如下所示:
public static TEntityId Parse(string val) {
var constr = typeof(TEntityId).GetConstructor(
// Since the constructor is private, you need binding flags
BindingFlags.Instance | BindingFlags.NonPublic
, null
, new[]{ typeof(string) }
, null);
if (constr == null) {
throw new InvalidOperationException("No constructor");
}
return (TEntityId)constr.Invoke(new object[] {val});
}
将值
设为私有可变字段/属性,并通过Parse
方法进行实际设置,如何
(为了简单起见,从EntityId
中删除了一个奇怪的重复出现的泛型参数)
澄清一下:您正在寻找抽象类上的方法publicstatictentyid Parse(stringvalue){…}
?此方法是否是EntityId
是抽象的唯一原因?因为我并没有看到它既通用又抽象的原因,至少在这个简化的例子中是这样。谢谢Rob,非常干净的解决方案。因为我不会在一个循环中创建数百个对象,在考虑了一会儿之后,我决定按照您的建议使用反射,因为这样我可以为其他使用该类库的开发人员(或几个月后的我自己)提供最容易阅读的API。拥有一个简单的AnimalEntityId.Parse(“ID”)对我来说是一个巨大的优势。我还开始添加对访问非公共构造函数的更改,并意识到,我拥有与@dasblinkenlightKirill建议的相同的代码,谢谢,这是一种非常有趣的方法。我决定在这种情况下使用反射,因为在这种情况下,我可以使API更干净:AnimalEntityId.Parse(“ID”)而不是EntityId.Parse(ID)。在您的建议中,我觉得实现细节正在泄漏,用户不应该看到这些细节。
public class SimpleAnimalEntityId : EntityId
{
// Implicit parameterless constructor.
}
public class ParametrizedAnimalEntityId : EntityId
{
// Parametrized constructor only.
public ParametrizedAnimalEntityId(int ignored)
{
}
}
public abstract class EntityId
{
// Simple scenario: derived type has a parameterless constructor.
public static TEntity Parse<TEntity>(string value)
where TEntity : EntityId, new()
{
Guid id = Guid.Parse(value);
return new TEntity { value = id };
}
// Advanced scenario: derived type constructor needs parameters injected.
public static TEntity Parse<TEntity>(string value, Func<TEntity> constructor)
where TEntity : EntityId
{
Guid id = Guid.Parse(value);
TEntity entity = constructor();
entity.value = id;
return entity;
}
private Guid value;
protected EntityId()
{
value = Guid.NewGuid();
}
}
string id = Guid.NewGuid().ToString();
SimpleAnimalEntityId simple = EntityId.Parse<SimpleAnimalEntityId>(id);
ParametrizedAnimalEntityId parametrized = EntityId.Parse(id, () => new ParametrizedAnimalEntityId(42));