У меня под рукой IntPtr
до IUnknown
управляемого объекта, где управляемый объект находится в другом домене приложения.Это означает, что указатель на это CCW.Я хотел бы разработать сигнатуру метода, которая возвращает это должным образом другим клиентам COM, таким как классический ASP.Что-то вроде этого:
[return: MarshalAs(UnmanagedType.IUnknown)]
public IntPtr Resolve(string typeName);
Однако это не работает..NET не достаточно умен, чтобы делать правильные вещи здесь.Метод выглядит как фактическое целочисленное значение.
Я не хочу возвращать object
, поскольку я не хочу разрешать фактический управляемый экземпляр, так как я не хочу, чтобы он пытался загрузитьсвязанная управляемая сборка в этом конкретном AppDomain
.Это IntPtr
связано с управляемым объектом, который поступает из другого AppDomain
.
[EDIT]
Некоторое дополнительное объяснение: я пытаюсь получить управляемые объекты COM из ASP.Net, которые находятся в AppDomain
, отличном от домена по умолчанию.Обычно, когда вы делаете CreateObject("managedobject")
, вы в конечном итоге создаете экземпляр в рамках AppDomain
процесса по умолчанию.Вместо этого я предоставляю прокси для разрешения объектов из другого домена приложений.Таким образом, это означает, что мой прокси находится в домене по умолчанию, но его метод Resolve
возвращает управляемый объект из другого домена и возвращает его обратно вызывающему COM-клиенту.
Полный вариант использования: у меня естьклассический ASP и ASP.Net в одном процессе.Я хочу разрешить управляемые объекты .NET, которые находятся в одном домене приложений одного и того же сайта, который объединяет их.ASP.Net генерирует домен приложений для каждого сайта.Однако ASP, будучи неуправляемым, ничего не знает об этом.Однако это управляемый конвейер IIS, поэтому он должен работать.
Дополнительное примечание: у меня на сайте ASP.Net имеется контейнер Autofac, из которого я хочу разрешить объекты.
Да, я пытаюсь использовать Autofac и DI из классического ASP.Сумасшедшие времена!
Оказывается, я заставил его работать:
/// <summary>
/// Resolves an object from the container.
/// </summary>
/// <param name="typeName"></param>
/// <returns></returns>
[return: MarshalAs(UnmanagedType.IUnknown)]
public object Resolve(string typeName)
{
var ptr = (GetProxy() ?? GetGlobalProxy())?.Resolve(typeName) ?? IntPtr.Zero;
if (ptr == IntPtr.Zero)
return null;
// resolve to RCW, which .Net can marshal correctly
var obj = Marshal.GetObjectForIUnknown(ptr);
Marshal.Release(ptr);
return obj;
}
Это сгенерировало RCW для удаленного CCW.Который может быть помечен как IUnknown правильно.Это технически ненужный объект, я думаю, поскольку исходный COM-объект может правильно получать эти вызовы, и нам фактически не нужно передавать его с RCW.Но это делает маршаллера счастливым.
Все еще ищет лучшие решения.
Итак, мой вариант использования работает.В Классическом ASP я могу сделать это:
<object runat="server" scope="Application" id="ComponentContext" progid="Cogito.Autofac.Asp.ComponentContextProxy"></object>
С последующим Set obj = ComponentContext.Resolve("Cogito.Autofac.Asp.Sample.Objects.ResolvableObject, Cogito.Autofac.Asp.Sample.Objects")
на странице ASP.И это разрешает объект из Autofac.Красивые.