获取实例化对象的代码的汇编(具有继承)

时间:2015-03-15 13:16:47

标签: c# .net inheritance assembly-resolution

我有一个抽象类,需要能够加载包含在构成该类对象的程序集中的文件。对于我班上的每个孩子,我可以使用的是FileAssembly = Assembly.GetCallingAssembly(),但由于它是一个人们可以扩展的图书馆,我希望这样做而不要求他们这样做。

我现在的设置是:

public abstract class ExternalResource : Resource, IDisposable
{
    public string File { get; private set; }
    protected Assembly FileAssembly { get; set; }

    protected ExternalResource(string id, string file)
        : base(id)
    {
        File = file;
    }

    //and s'more code
}

public class Sound : ExternalResource
{
    public Sound (string id, string file)
        : base(id, file)
    {
        //this is the line I want to be able to get rid of
        FileAssembly = Assembly.GetCallingAssembly();
    }
}

使用我的库的人可以在不设置FileAssembly的情况下创建自己的ExternalResource,这是不可取的。如果它们从已经从ExternalResource继承的类继承,它会变得非常混乱。如何获取实例化对象的代码程序集?任何其他方式来解决它而不需要对现有系统进行太多改动也将受到赞赏!

2 个答案:

答案 0 :(得分:1)

您可以使用System.Diagnostics名称空间中的StackTrace类:

在ExternalResource类的构造函数中:

var stack = new StackTrace(true);
var thisFrame = stack.GetFrame(0); // ExternalResource constructor
var parentFrame = stack.GetFrame(1); // Sound constructor
var grandparentFrame = stack.GetFrame(2); // This is the one!

var invokingMethod = grandparentFrame.GetMethod();
var callingAssembly = invokingMethod.Module.Assembly;

对thisFrame和parentFrame的引用只是为了帮助理解。我建议你实际上走上堆栈框架并更加健壮地做,而不是假设它总是你想要的第2帧(如果你有一个额外的子类,它将不会给出正确的答案) )。

答案 1 :(得分:0)

使用调用程序集可能会让一些人感到沮丧,他们将ExternalResource相关代码移动到一个新的单独程序集中而没有意识到它具有程序集依赖性,或者想要将其资源移动到单独标识的程序集中(例如本地化)。

我的建议是:

  • 将一个显式的汇编参数添加到构造函数中,非常清楚它正在使用某个程序集执行某些操作。
  • 提供一种工厂方法,以便为用户确定调用程序集

如果所有派生类型都需要构造函数参数string id, string file,然后是新的显式汇编参数,那么您的工厂方法可能是通用的。类似的东西:

public static TExternalResource CreateExternalResource<TExternalResource>(string id, string file, Assembly assembly = null) where TExternalResource : ExternalResource
{

    var ResolvedAssembly = assembly ?? Assembly.GetCallingAssembly();

    return Activator.CreateInstance(typeof(TExternalResource), id, file, ResolvedAssembly) as TExternalResource;
}