2015-03-15 6 views
0

У меня есть абстрактный класс, который должен иметь возможность загружать файлы, содержащиеся в сборке, которые сделали объект класса. То, что я могу использовать, - 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(); 
    } 
} 

кто-то использует мою библиотеку могли бы сделать свой собственный ExternalResource без установки FileAssembly, что не желательно. Это становится действительно грязным, если они наследуют от класса, который уже наследует от ExternalResource. Как я могу получить сборку кода, создающего экземпляр объекта? Любой другой способ обойти его без чрезмерного изменения существующей системы тоже будет оценен!

+1

Вам нужна сборка вызывающего кода или сборка, которая определяет производный тип? –

+0

Вызывающий код, идея гласит, что везде, где должен быть поставлен файл, должна быть разрешенная сборка. – Villermen

ответ

1

Вы можете использовать класс StackTrace из пространства имен System.Diagnostics:

В конструкторе класса 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, который вы хотите (что не даст правильного ответа, если у вас есть дополнительный подкласс).

+0

Звук может быть унаследован снова, так что неясно, сколько уровней обратно создается объект. – Villermen

+1

Что делать, если я создаю ' ExtendedSound', который наследуется от 'Sound' и т. Д.? –

+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; 
} 
+0

Это была моя идея, чтобы это произошло прозрачно, потому что я хотел, чтобы было ясно, что везде, где должен быть поставлен файл, должна быть сборка, в которой он проверяет. Я также мог бы всегда быть сборкой записей, но я не знаю, как это будет работать, когда люди, например, добавляя сборку, которая расширяет сборку записей с ее собственными содержащимися файлами. Я хочу, чтобы это было как можно проще для людей, использующих библиотеку (иначе они просто будут использовать один и тот же код (currentassembly) в любом случае. – Villermen

+0

Я понимаю фактор удобства, который вы пытаетесь достичь, но я все же утверждаю, что пытаюсь угадать сборка (и не предоставление какой-либо другой опции вместо этого предоставить сборку) является плохой формой для библиотеки. –

 Смежные вопросы

  • Нет связанных вопросов^_^