作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下代码在 RegistrationBuilder
时不起作用用来。当RegistrationBuilder
未添加到 AssemblyCatalog 构造函数中,类型约束泛型起作用。
[TestClass]
public class TypeConstraints
{
[TestMethod]
public void TypeConstraintTest()
{
var rb = new RegistrationBuilder();
var a = new AssemblyCatalog(Assembly.GetExecutingAssembly(), rb);
//var a = new AssemblyCatalog(Assembly.GetExecutingAssembly()); //Works!
var aggr = new AggregateCatalog(a);
var c = new CompositionContainer(aggr);
var item = c.GetExportedValue<IConstrained<Item>>();
Assert.IsNotNull(item);
}
}
public interface IConstrained<T> where T : IItem
{}
[Export(typeof (IConstrained<>))]
public class Constrained<T> : IConstrained<T> where T : IItem
{}
public class Item : IItem
{}
public interface IItem
{}
最佳答案
首先,让我们描述一下究竟是什么导致了这种行为。
RegistrationBuilder 将程序集的实际类型包装在称为 CustomType 的代理类型中。这个代理或多或少只是为了让 RegistrationBuilder 有机会即时注入(inject) Export 和 Import 属性。
遗憾的是,当您调用 GetGenericParameterConstraints 时,此代理也会返回包装类型。所以它不是一个 RuntimType IItem 你得到它是一个 CustomType IItem。当您尝试获取 IConstrained 的导出时,AssemblyCatalog 会检查很多内容以判断您的导出是否与您的导入匹配。其中一项检查是是否满足泛型类型约束。或多或少是这样的支票。 (简化)
exportToCheck.GenericTypeConstraints[0].IsAssignableFrom(typeof(Item))
public override bool IsAssignableFrom(Type c)
{
ProjectingType projectingType = c as ProjectingType;
return !(projectingType == null) && this.Projector == projectingType.Projector &&
base.UnderlyingType.IsAssignableFrom(projectingType.UnderlyingType);
}
private bool projectionsChecked = false;
public MyAssemblyCatalog(Assembly assembly, CustomReflectionContext reflectionContext)
: base(assembly, reflectionContext)
{
this.ReflectionContext = reflectionContext;
}
public CustomReflectionContext ReflectionContext { get; private set; }
public Type Unproject(Type type)
{
if (this.unprojectDelegate == null) {
var param = Expression.Parameter(typeof(CustomReflectionContext));
var param2 = Expression.Parameter(typeof(Type));
var prop = Expression.Property(param, param.Type.GetProperty("Projector", BindingFlags.Instance | BindingFlags.NonPublic));
var method = prop.Type.GetMethod("Unproject", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(Type) }, null);
var body = Expression.Call(prop, method, param2);
this.unprojectDelegate = Expression.Lambda<Func<CustomReflectionContext, Type, Type>>(body, param, param2).Compile();
}
return unprojectDelegate(this.ReflectionContext, type);
}
private void EnsureUnprojectedGenericTypeConstraints()
{
if (!this.projectionsChecked) {
foreach (var item in this) {
object value1;
if (item.Metadata.TryGetValue("System.ComponentModel.Composition.GenericParameterConstraints", out value1)) {
var items = (object[])value1;
foreach (var entry in items) {
var types = entry as Type[];
if (types != null) {
for (int i = 0; i < types.Length; i++) {
types[i] = Unproject(types[i]);
}
}
}
}
}
projectionsChecked = true;
}
}
public override System.Collections.Generic.IEnumerable<Tuple<ComposablePartDefinition, ExportDefinition>> GetExports(ImportDefinition definition)
{
EnsureUnprojectedGenericTypeConstraints();
return base.GetExports(definition);
}
[TestMethod]
public void TypeConstraintTest()
{
var rb = new RegistrationBuilder();
var a = new MyAssemblyCatalog(Assembly.GetExecutingAssembly(), rb);
var aggr = new AggregateCatalog(a);
var c = new CompositionContainer(aggr);
var item = c.GetExportedValue<IConstrained<Item>>();
Assert.IsNotNull(item);
}
关于.net - 类型受限的开放泛型不适用于 RegistrationBuilder,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24590096/
我是一名优秀的程序员,十分优秀!