Результаты моего исследования на эту тему:
Проблема связана с реализацией IDispatch, используемой во время выполнения общеязыкового языка при представлении двойных интерфейсов и диспинтерфейсов для COM.
Язык сценариев, такой как VBScript (ASP), использует реализацию IDispatch автоматизации OLE при доступе к COM-объекту.
Несмотря на то, что это похоже на работу, я хочу сохранить свойство как свойство и не хочу иметь функцию (обходной путь объяснен выше).
У вас есть 2 возможных решения:
1 - использовать устаревший атрибут IDispatchImpl с IDispatchImplType.CompatibleImpl.
[ClassInterface(ClassInterfaceType.None)]
[IDispatchImpl(IDispatchImplType.CompatibleImpl)]
public class TestRequest : IRequest
{
private IRequestDictionary _queryString = new RequestDictionary();
public IRequestDictionary QueryString
{
get { return _queryString; }
}
}
Как сказано в MSDN, этот атрибут устарел, но все еще работает с .Net 2.0, 3.0, 3.5, 4.0.
Вы должны решить, может ли тот факт, что он «устарел», стать для вас проблемой ...
2 - Или реализуйте IReflect в качестве пользовательского IDispatch в своем классе TesRequest или создайте универсальный класс, который реализует IReflect и заставляет ваш класс наследовать этот новый созданный.
Образец общего класса (интересующая часть находится в методе InvokeMember):
[ComVisible(false)]
public class CustomDispatch : IReflect
{
// Called by CLR to get DISPIDs and names for properties
PropertyInfo[] IReflect.GetProperties(BindingFlags bindingAttr)
{
return this.GetType().GetProperties(bindingAttr);
}
// Called by CLR to get DISPIDs and names for fields
FieldInfo[] IReflect.GetFields(BindingFlags bindingAttr)
{
return this.GetType().GetFields(bindingAttr);
}
// Called by CLR to get DISPIDs and names for methods
MethodInfo[] IReflect.GetMethods(BindingFlags bindingAttr)
{
return this.GetType().GetMethods(bindingAttr);
}
// Called by CLR to invoke a member
object IReflect.InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] namedParameters)
{
try
{
// Test if it is an indexed Property
if (name != "Item" && (invokeAttr & BindingFlags.GetProperty) == BindingFlags.GetProperty && args.Length > 0 && this.GetType().GetProperty(name) != null)
{
object IndexedProperty = this.GetType().InvokeMember(name, invokeAttr, binder, target, null, modifiers, culture, namedParameters);
return IndexedProperty.GetType().InvokeMember("Item", invokeAttr, binder, IndexedProperty, args, modifiers, culture, namedParameters);
}
// default InvokeMember
return this.GetType().InvokeMember(name, invokeAttr, binder, target, args, modifiers, culture, namedParameters);
}
catch (MissingMemberException ex)
{
// Well-known HRESULT returned by IDispatch.Invoke:
const int DISP_E_MEMBERNOTFOUND = unchecked((int)0x80020003);
throw new COMException(ex.Message, DISP_E_MEMBERNOTFOUND);
}
}
FieldInfo IReflect.GetField(string name, BindingFlags bindingAttr)
{
return this.GetType().GetField(name, bindingAttr);
}
MemberInfo[] IReflect.GetMember(string name, BindingFlags bindingAttr)
{
return this.GetType().GetMember(name, bindingAttr);
}
MemberInfo[] IReflect.GetMembers(BindingFlags bindingAttr)
{
return this.GetType().GetMembers(bindingAttr);
}
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr)
{
return this.GetType().GetMethod(name, bindingAttr);
}
MethodInfo IReflect.GetMethod(string name, BindingFlags bindingAttr,
Binder binder, Type[] types, ParameterModifier[] modifiers)
{
return this.GetType().GetMethod(name, bindingAttr, binder, types, modifiers);
}
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr,
Binder binder, Type returnType, Type[] types,
ParameterModifier[] modifiers)
{
return this.GetType().GetProperty(name, bindingAttr, binder,
returnType, types, modifiers);
}
PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr)
{
return this.GetType().GetProperty(name, bindingAttr);
}
Type IReflect.UnderlyingSystemType
{
get { return this.GetType().UnderlyingSystemType; }
}
}
и для кода Майка:
[ClassInterface(ClassInterfaceType.None)]
public class TestRequest : CustomDispatch, IRequest {
private IRequestDictionary _queryString = new RequestDictionary();
public IRequestDictionary QueryString {
get { return _queryString; }
}
}