[英]Constraint parameters, new()
Is there any way to move the Parse method into the abstract class ? 有没有办法将Parse方法移动到抽象类中 ? I tried multiple ways (links at the bottom), but I am still hitting one or another roadblock. 我尝试了多种方式(底部的链接),但我仍然遇到一个或另一个障碍。
public class AnimalEntityId : EntityId<AnimalEntityId>
{
public AnimalEntityId()
: base()
{
}
private AnimalEntityId(string value)
: base(value)
{
}
public static AnimalEntityId Parse(string value)
{
return new AnimalEntityId(value);
}
}
public abstract class EntityId<TEntityId>
{
private readonly System.Guid value;
protected EntityId(string value)
{
this.value = System.Guid.Parse(value);
}
protected EntityId()
{
this.value = System.Guid.NewGuid();
}
}
Tried these suggestions with no luck: 试试这些建议没有运气:
Passing arguments to C# generic new() of templated type 将参数传递给模板化类型的C#generic new()
Is there a generic constructor with parameter constraint in C#? 在C#中是否存在具有参数约束的通用构造函数?
https://social.msdn.microsoft.com/Forums/en-US/fd43d184-0503-4d4a-850c-999ca58e1444/creating-generic-t-with-new-constraint-that-has-parameters?forum=csharplanguage https://social.msdn.microsoft.com/Forums/en-US/fd43d184-0503-4d4a-850c-999ca58e1444/creating-generic-t-with-new-constraint-that-has-parameters?forum=csharplanguage
Thanks in advance! 提前致谢!
No, you cannot write a template constraint such as new(string)
instead of simply new()
. 不,你不能写一个模板约束,比如new(string)
而不是new()
。 You'll have to leverage reflection to get it to work: 你必须利用反射才能让它发挥作用:
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 });
}
}
Assuming you make the constructor accessible (instead of it currently being private). 假设您使构造函数可访问 (而不是当前是私有的)。 Note the constraint where TEntityId : EntityId<TEntityId>
- which will ensure we'll only return subclasses of EntityId
注意where TEntityId : EntityId<TEntityId>
的约束 - 这将确保我们只返回EntityId
子类
If you don't mind using reflection, you can move Parse
into the abstract type like this: 如果您不介意使用反射,可以将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});
}
How about making value
a private mutable field/property and actually setting it from the Parse
method? 如何将value
设为私有可变字段/属性并实际从Parse
方法设置它?
(Curiously recurring generic parameter removed from EntityId
for simplicity) (为简单起见,从EntityId
删除了奇怪的重复通用参数)
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();
}
}
Now you can handle any constructor from your Parse
method: 现在您可以使用Parse
方法处理任何构造函数:
string id = Guid.NewGuid().ToString();
SimpleAnimalEntityId simple = EntityId.Parse<SimpleAnimalEntityId>(id);
ParametrizedAnimalEntityId parametrized = EntityId.Parse(id, () => new ParametrizedAnimalEntityId(42));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.