2012-01-15 7 views
3

Сценарий, идет как это -объекты класса Passing через различные версии сборки

  • У меня есть сборка сказать «MyAssembly». Интерфейс «IMyInterface» определен в этой сборке.
  • В той же сборке, у меня есть один класс (MyClass) с методом определения в нем, как:

общественной ничтожной MyMethod (IMyInterface объект) {}

  • Теперь в моем project, я создал интерфейс с тем же именем и точными свойствами, которые были открыты интерфейсом «IMyInterface» в «MyAssembly».
  • У меня есть класс, который расширяет этот интерфейс (тот, который я создал в моем проекте), и я хочу передать объект этого класса в качестве параметра методу «MyMethod» в другой сборке с использованием отражения.

Проблема есть -

  • Когда я пытаюсь вызвать метод с помощью отражения, я получил это исключение, которое «Не удается преобразовать объект к типу IMyInterface».

код -

Assembly myAssembly = Assembly.LoadFrom("MyAssembly"); 
object classObject = myAssembly.CreateInstance("MyClass"); 
Type classType = myAssembly.GetType("MyClass"); 
MethodInfo myMethod = classType.GetMethod("MyMethod", BindingFlags.Instance); 

// Creating an object of class in the latest assembly and need to pass this 
// to method in assembly with different version. 
ClassExtendingMyInterface obj= new ClassExtendingMyInterface(); 

myMethod.Invoke(classObject, new object[] { obj}); 

Если я получаю это правильно, это происходит потому, что объект, созданный в другой сборке и параметр, ожидаемый методом является его собственной сборки.

Другой подход, о котором я думал, заключался в том, чтобы создать свой собственный динамический метод в классе, который примет объект моего класса.

Я попытался Google для и попадались через Reflection.Emit или RunSharp динамически создать свой собственный класс. Но мы можем использовать это только в наших динамически сгенерированных сборках, но не можем создавать динамические методы или класс в уже существующей сборке.

Я знаю, что сборка сборок во время выполнения - это не очень хороший подход. Но сейчас я ничего не могу придумать. Спасибо за любую помощь.

ответ

6

Вы сражаетесь с чем-то, называемым «идентификатором типа», очень важной встречной мерой DLL Hell в платформе .NET. Тип не просто идентифицируется по имени его имени и имени типа, он также включает атрибуты сборки, из которой она была создана. В частности, отображаемое имя сборки, [AssemblyVersion], [AssemblyCulture], PublicKeyToken и (косвенно) ProcessorArchitecture. Вы можете увидеть имя типа «real» с свойством Type.AssemblyQualifiedName. Класс System.String, например, System.String, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Это мешает вам приклеивать тип в другой сборке, если вы не можете дать этой сборке те же самые атрибуты. Намного проще просто использовать существующую сборку, не должно быть проблем в вашем случае, поскольку вы используете только интерфейс.

Примечательно, что это требование было несколько смягчено в .NET 4. Типы, которые были автоматически сгенерированы из библиотеки типа COM, эквивалентны, если их имя и [Guid] совпадают. Это помогло устранить PIA и реализовать функцию «Вставить типы взаимодействия». Ничего, что применимо в вашем случае.

+0

> Намного проще просто использовать существующую сборку, не должно быть проблем в вашем потому что вы используете только интерфейс. Но я хочу свою собственную реализацию (способ реализации этого интерфейса) и хочу, чтобы этот объект был передан. Но поскольку эта реализация не может быть в существующей сборке, поскольку она уже развернута Не могу изменить эту сборку :(Вот почему я пытался реализовать ее в новой версии сборки и передал ее как параметр через отражение. Могу ли я достичь этого каким-то другим способом, если вы можете помочь .. спасибо .. :) –

+0

Я не понимаю, почему это проблема, просто используйте копию развернутой сборки и добавьте ее в качестве ссылки на ваш проект. для взломов. –

+0

Я не могу добавить ссылку на assmebly, так как мне нужно загрузить сборку во время выполнения в зависимости от некоторых случаев использования. Мне нужно загрузить сборку на основе некоторых пользовательских сценариев .. :( –

1

Здесь:

Теперь в моем проекте, я создал интерфейс с таким же именем и точными свойствами, раскрываемый интерфейсом «IMyInterface» в «MyAssembly».

В этом проблема; недостаточно объявить интерфейс с похожим именем. Типы охвачены их сборкой; то есть для CLR, совершенно другого интерфейса.

Вместо этого добавьте ссылку в исходную сборку и реализуйте интерфейс, который уже определен. Его следует определять только один раз.

+0

Я не могу добавить ссылку на assmebly, так как мне нужно загрузить сборку во время выполнения в зависимости от некоторых случаев использования. :( –

1

Если я правильно понимаю вашу проблему, я считаю, что вы хотите определить свои интерфейсы в своей собственной сборке, а затем ссылаться на общую сборку интерфейсов изнутри каждой из двух других. Таким образом, каждый узел ссылается на то же определение интерфейса:

Создать и построить MyInterfaces DLL:

namespace MyInterfaces 
{ 
    public interface IMyInterface 
    { 
     void SharedMethod(); 
    } 
} 

Затем создать свой первый узел в другом проекте, и установить ссылку на DLL, созданный для MyInterfaces , Создать свой класс, отмечая «используя» заявление в верхней части модуля:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using MyInterfaces; 

namespace MyFirstProject 
{ 
    public class MyClass1 
    { 
     public void MyMethod(IMyInterface SomeObject) { } 
    } 
} 

Теперь, я полагаю, ваше творение динамического объекта должно работать, так как объекты реализуют одинаковый интерфейс, определенный в «MyInterfaces».

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

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