【问题标题】:Is there currently a way to instantiate an internal class using .NET Standard?目前有没有办法使用 .NET Standard 实例化内部类?
【发布时间】:2017-05-08 13:15:14
【问题描述】:

很长一段时间以来,我一直在寻找解决方案 - 考虑到这应该是多么简单。我有一个针对netstandard1.5net451 的库。它在net451 中运行良好。整个库中的一个类中有一个方法使用 .NET 反射创建具有来自另一个库的内部构造函数的类型的实例(也针对 netstandard1.5net451)。

但是,我需要接受BindingFlagsActivator.CreateInstance 的重载...

public static object CreateInstance(Type type, BindingFlags bindingAttr, Binder binder, object[] args, CultureInfo culture)

...在netstandard1.5 甚至netstandard1.6 中不可用。我看到它will be in netstandard2.0,但尚未发布。

我尝试创建一个可移植类库,但我似乎无法从中引用以netstandard1.5 为目标的依赖库。我只是得到错误:

Severity    Code    Description Project File    Line    Suppression State
Error       Package OtherPackage 3.1.0-beta00001 is not compatible with dotnet5.0 (.NETPlatform,Version=v5.0). Package OtherPackage 3.1.0-beta00001 supports:
    - net451 (.NETFramework,Version=v4.5.1)
    - netstandard1.5 (.NETStandard,Version=v1.5)                

那么,如果您在内部成员上使用反射,目前真的没有支持 .NET Core 的方法吗?如果有,怎么办?

【问题讨论】:

  • 我知道它不能总是完成,但如果你在图书馆之外需要它,为什么不把它改成public 类呢?或者,如果它不应该在图书馆外使用,你为什么还要使用它?
  • 1) 内部构造函数位于不同的库中。 2)该设计是Java的一个端口,它在与另一个库相同的命名空间中创建了一个类,这在Java中似乎足以实例化该类。在 .NET 中使用反射似乎没有替代方法。
  • Activator.CreateInstance 并不神奇,至少在涉及常规 .NET 类型的情况下如此。这并不比获得适当的ConstructorInfo (TypeInfo.GetConstructor) 并为此调用Invoke 更重要。我不知道netstandard 的完整表面,所以我不知道它是否足够支持反射,但它是一种替代方案。也就是说,无论是否从 Java 移植,这种设计在 .NET 中都不是很好。需要彼此 internals 的类型应该是同一个程序集的一部分,因为它们是显式耦合的。
  • @JeroenMostert - 我也研究过使用ConstructorInfo.Invoke,但也没有办法将BindingFlags 传递给它。 GetConstructor() 的默认行为只能使用公共构造函数(但如果它是公共的,我就不需要 Reflection)。
  • 根据docsTypeInfo.GetConstructors(BindingFlags)(注意复数)在netstandard1.5中可用。

标签: c# .net .net-core .net-standard


【解决方案1】:

虽然netstandard1.5 缺乏反射的全部功能,但基础知识是可用的。给定一个类T,它有一个无参数构造函数(不管可见性如何),这就是动态构造实例的方式:

ConstructorInfo c = typeof(T)
    .GetTypeInfo()
    .DeclaredConstructors
    .Single(ci => ci.GetParameters().Length == 0)
;
T t = (T) c.Invoke(Type.EmptyTypes);

如果您知道该类型无论如何只有一个构造函数(您可以改用.First,或省略谓词),则对.Single() 的调用不是绝对必要的,但无论如何还是强烈建议包含它,以免代码如果将来添加构造函数,则中断。

【讨论】:

  • 好多了 - 不傻BindingFlags。构造函数有 6 个参数,所以我最终得到了var constr = typeof(AtomicReaderContext).GetTypeInfo().DeclaredConstructors.Single(constructor => constructor.GetParameters().Select(parameter => parameter.ParameterType).SequenceEqual(constructorTypeArray));
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
  • 2012-09-16
相关资源
最近更新 更多