有没有办法强制传递给属性的类型参数实现特定的接口?
public interface IExpectedInterface
{
void InterfaceMethod();
}
public class MyCustomAttribute : Attribute
{
public MyCustomAttribute(Type classType)
{
this.ConfirmAssignedClassType();
_classType = classType;
}
public void SomeMethod<T>() where T : IExpectedInterface, new()
{
//var expectedType = Activator.CreateInstance(this._classType) as IExpectedInterface;
var expectedType = Activator.CreateInstance(typeof(T)) as IExpectedInterface;
if (expectedType == null)
{
// Wrong type
throw new ArgumentException(string.Format("Wrong type: {0} could not be created or converted to IActionAuthorization", _classType.ToString()));
}
// Do something with expectedType
expectedType.InterfaceMethod();
}
private void ConfirmAssignedClassType()
{
if (!typeof(IExpectedInterface).IsAssignableFrom(_classType))
{
// Wrong type
// Can we enforce it via language construct
throw new ArgumentException(string.Format("Wrong type: {0} must implement IExpectedInterface", _classType.ToString()));
}
if (this._classType.GetConstructor(Type.EmptyTypes) == null)
{
// Wrong type
// Can we enforce it via language construct
throw new ArgumentException(string.Format("Wrong type: {0} must have parameter less constructor", _classType.ToString()));
}
}
private Type _classType;
}
public class TestClass
{
[MyCustom(typeof(TestClassImplementsExpectedInterface))]
public void TestMethod1()
{
}
[MyCustom(typeof(TestClassDoesntImplementExpectedInterface))]
public void TestMethod2()
{
}
}
public class TestClassImplementsExpectedInterface : IExpectedInterface
{
public void InterfaceMethod()
{
return;
}
}
public class TestClassDoesntImplementExpectedInterface
{
}
答案 0 :(得分:5)
这不能用泛型来完成吗? (已编辑 - 无法创建属性的通用子类)
public class MyAttribute: Attribute
{
private Type _ClassType;
public MyAttribute(Type classType)
{
_ClassType = classType;
}
public void SomeMethod<T>() where T: IMyInterface
{
var expectedType = Activator.CreateInstance(typeof(T)) as IMyInterface;
// Do something with expectedType
}
}
当然,另一个答案是使用“new”的翻译很有意义!
答案 1 :(得分:3)
如果由于某种原因你不想搞乱泛型(例如将所有属性放入列表或其他东西),那么可能会考虑稍微更好的方法,尽管仍然没有编译时检查。您可以调用Type.IsAssignableFrom方法,而不是调用Activator.CreateInstance(根据是否存在0-param ctors,可能会也可能不会起作用)(尽管您似乎假设存在0-param ctor,所以这可能有些没有实际意义。)
if (!typeof(SomeInterface).IsAssignableFrom(_ClassType)))
// Throw exception
答案 2 :(得分:2)
您可以将方法转换为通用方法,例如
public class MyAttribute : Attribute
{
public void SomeMethod<T>() where T : ISomeInterface, new()
{
var expectedType = new T();
// Do something with expectedType
}
}
new()
类型约束意味着该类型必须具有公共的无参数构造函数,这意味着您可以执行new T()
。这样就无需使用Activator
。
请注意,正如Duncan Howe指出的那样,泛型类型无法继承Attribute
,因此您无法public class MyAttribute<T> : Attribute
答案 3 :(得分:0)
为什么不通过构造函数(例如Public MyAttribute(IMyInterface myObject)
)传递对象并将其存储在属性中。然后,如果您需要该类型,请显式调用typeof(myObjectProperty)
。