【问题标题】:How to pass the name of a class as paramenter to a method and instantiate that class inside the method?如何将类的名称作为参数传递给方法并在方法内实例化类?
【发布时间】:2019-09-18 08:14:35
【问题描述】:

我希望能够将类名作为参数传递给方法,然后在该方法中创建具有某些参数的该类的对象。

一个具体(简化)的例子:

这是一种计算 OperationResult 的方法

private IOperationResult<Unit> GetFailedOperationResult(IEnumerable<StrictSide> sides, IFailedOperationInfo failedOperationResult)
{
    var exception = failedOperationResult.Exception.HasValue() ? failedOperationResult.Exception.Value() : null;
    if (exception != null)
    {
        return new FailedResult<Unit>(
            new InvalidBundleErrorKeyResolver(new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName, sides), exception)));
    }
    throw new InvalidOperationException("Failed operation result during bundle consistency check does not contain error or exception.");
}

根据我们从中获取错误的操作,我们使用不同的 ErrorKeyResolver。我想将这些 ErrorKeyResolver 作为参数传递给方法,这样我就不需要为每种错误类型制作不同的 GetFailedOperationResult 方法了。

灵感来自How to use class name as parameter in C# 我试过这样的事情:

private IOperationResult<Unit> GetFailedOperationResult(IEnumerable<StrictSide> sides,IFailedOperationInfo failedOperationResult, IErrorResourceKeyResolver resourceKeyResolver)
{
    var exception = failedOperationResult.Exception.HasValue() ? failedOperationResult.Exception.Value() : null;
    if (exception != null)
    {
        return new FailedResult<Unit>(Activator.CreateInstance(typeof(resourceKeyResolver),new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName, sides), exception)));
    }
    throw new InvalidOperationException("Failed operation result during bundle consistency check does not contain error or exception.");
}

但我不能这样做typeof(resourceKeyResolver),因为我不能使用变量作为类型。

有什么好的方法可以做到这一点吗?这甚至是一件好事吗?我还读到应该避免动态,所以我想知道在这里保存一些代码重复是否值得。

EDIT:输入参数应为:private IOperationResult&lt;Unit&gt; GetFailedOperationResult(IEnumerable&lt;StrictSide&gt; sides,IFailedOperationInfo failedOperationResult, string resourceKeyResolver)

从类名作为字符串我应该能够找到类型。

【问题讨论】:

  • typeof(resourceKeyResolver) 应该是resourceKeyResolver.GetType()
  • 你可以使用Inversion Of Control
  • 它没有意义......如果你有它的实例(resourceKeyResolver),为什么要创建由resourceKeyResolver.GetType() 表示的类的实例? ...这看起来像 XY 问题
  • @Selvin 你是对的。实际上我理解输入参数应该只是作为字符串的类名,而不是它的实例。我会更新问题。
  • Activator.CreateInstance 的重载方法需要 2 个字符串 - 程序集和类名...问题出在哪里?

标签: c# parameter-passing


【解决方案1】:

如果你将类作为接口传递,你可以使用下面的代码来实例化解析器

var resolver = Activator.CreateInstance(resourceKeyResolver.GetType(),
new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName, 
sides), exception));

否则,如果你使用类名(assembly-qualified-name),你可以例如先将其转换为类型,然后再次调用上述行

var resolverType = Type.GetType(resourceKeyResolverClassName);
var resolver = Activator.CreateInstance(resolverType ,
new FailedOperationInfo(new OperationInfo(failedOperationResult.OperationName, 
sides), exception));

有关GetType() 方法的文档,请参阅here

【讨论】:

  • Type.GetString(resourceKeyResolver); 你的意思是输入Type.AssemblyQualifiedName
  • 是的,更新了描述并添加了指向文档的链接以使其清晰
  • Ehhhm,现在更加混乱了。没有定义方法GetString,只有GetType。但是,您不能在 resourceKeyResolver 实际是的实例上调用后者。
  • 谢谢@tchrikch。正如 HimBromBeere 所提到的,对于答案的第二部分,我想您的意思是 Type.GetType(String) 如果类名以字符串形式给出(这也是您发布的链接)。
猜你喜欢
  • 1970-01-01
  • 2022-01-05
  • 2019-03-26
  • 2020-01-26
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多