如果标题不太具有描述性,我很抱歉,我很难想出一个。
我有一个抽象基类,其属性之一是泛型类型。
public abstract class AdapterBase<T>
{
public string AdapterName { get; set; }
public T? Configuration { get; set; }
}
我想从抽象类派生并传递配置属性的类型信息。
public class FooAdapter : AdapterBase<FooConfiguration>{}
public class BarAdapter : AdapterBase<BarConfiguration>{}
两个配置对象都有不同的属性,一个可能有名称,另一个只有 Guid。然而,附加到每个配置类我都有一个属性。
[MyCustomAttribute("Foo")]
public class FooConfiguration{}
[MyCustomAttribute("bar")]
public class BarConfiguration{}
现在我想调用一个通用函数,仅检查配置字段中属性是否存在
public bool AdapterConfigurationHasMyCustomAttribute<T>()
{
....
}
...
main()
{
bool isThere = AdapterConfigurationHasMyCustomAttribute<FooAdapter>(); => returns true
}
我的问题是,如果我不指定 T 属于 AdapterBase,那么我无法访问函数内 T 的任何属性。 所以我必须用 where 子句来约束类型
public bool AdapterConfigurationHasMyCustomAttribute<T>() where T : AdapterBase<U>
{
....
}
这对我来说很好。然而,这个解决方案要求我还提供 U 的类型信息,这将使签名看起来像这样。
public bool AdapterConfigurationHasMyCustomAttribute<T,U>() where T : AdapterBase<U> where U: class, new()
{
....
}
但是,我希望保留单一类型的签名,因为 U 的类型已经通过定义 T 进行了定义。添加另一种类型也意味着像这样的调用:
主要的()
{
bool isThere = AdapterConfigurationHasMyCustomAttribute
会导致 True,即使 FooAdapter 和 BarConfiguration 不属于一起。
我可以通过像这样传递一个对象作为参数来规避它。
public bool AdapterConfigurationHasMyCustomAttribute<T>(AdapterBase<T> myAdapter) where T : class, new()
{
....
}
但是当我只需要附加到类型的信息时实例化一个对象对我来说似乎有点过分了。
同样,我想避免这样的调用,我传递配置类型:
main()
{
bool isThere = AdapterConfigurationHasMyCustomAttribute<FooConfiguration>();
}
这是因为如果其他人要使用该代码,他们需要事先了解哪个 Configuration-Type 属于哪个 AdapterBase 派生,否则他们以后可能会犯错误。
main()
{
BarAdapter = new BarAdapter();
bool isThere = AdapterConfigurationHasMyCustomAttribute<FooConfiguration>();
if(isThere)
{
//doing something with BarAdapter after checking FooConfiguration
}
}
我希望方法签名看起来像这样。
public bool AdapterConfigurationHasMyCustomAttribute<T>() where T : AdapterBase<U> where U: class, new()
{
....
}
有没有一种方法可以让我避免传递第二种类型,同时确保 T 始终是 AdapterBase 的派生?
您可以通过使用反射检查 T 上的属性来实现此目的。修改您的方法如下:
public bool AdapterConfigurationHasMyCustomAttribute<T>() where T : AdapterBase<object>
{
Type configType = typeof(T).GetProperty("Configuration")?.PropertyType;
if (configType != null)
{
var attribute = configType.GetCustomAttribute<MyCustomAttribute>();
if (attribute != null && attribute.SomeProperty == "desiredValue")
{
return true;
}
}
return false;
}
它限制 T 为 AdapterBase 的派生类,因为您想要访问 Configuration 属性,并且它的类型事先未知。