我正在开发一个项目,它是一个相当大的经典ASP项目的.NET扩展,使用了很多C ++ COM对象,这些对象永远存在于我们的代码库中。不幸的是,在C ++方面有很多hack-ish代码,我担心我没有足够的经验来解决我遇到的问题。
简而言之,我可以实例化有问题的COM对象,Visual Studio告诉我,我应该能够调用它的“方法”(在引号中,因为它们实际上是作为参数化属性公开的)。但是,我尝试调用的任何方法都给出了错误“索引属性'CoreAspLib.IComUser.LoginUser'具有必须提供的非可选参数。”问题是,我使用的是与传统ASP世界中使用的完全相同的参数,甚至属性的IntelliSense帮助告诉我我正在使用正确的参数集。例如,“LoginUser”属性的签名是“dynamic IComUser.get_LoginUser(string username,string password)”,我用两个字符串调用它,但我仍然得到“非可选参数”错误。
这是一些相关的代码 - 首先,我正在尝试进行方法调用的类。 CComUtils
是一个辅助类,它只接受COM的GUID和对目标对象的引用,创建所需COM对象的实例,并将目标引用分配给新对象。
public static class CurrentUser
{
public static void Authenticate(string userName, string password)
{
CoreAspLib.ComUser userObject = Cache.Request<CoreAspLib.ComUser>("UserComObject");
if (userObject == null) {
Guid userGuid = new Guid("BF748C0A-450D-4EAF-8C39-A36F6B455587");
CComUtils.CreateCOMInstance(userGuid, ref userObject);
Cache.Request("UserComObject", userObject);
}
var result = userObject.LoginUser(sUserName:"foo", sPassword:"bar");
if (result.Failed) {
throw (new System.Security.Authentication.InvalidCredentialException("Bad username or password".tr()));
} else {
FormsAuthentication.SetAuthCookie(userName, false);
}
}
}
这是来自COM对象源的实际方法签名:
STDMETHODIMP CComUser::get_LoginUser(BSTR bsUserName, BSTR bsPassword, IDispatch ** pResult)
以下是IDL的接口定义:
[
object,
uuid(1F4D8A57-BDE1-4D47-A9BC-5F541A0ED184),
dual,
nonextensible,
helpstring("IComUser Interface"),
pointer_default(unique)
]
interface IComUser : IDispatch{
[propget, id(1), helpstring("property LoginUser")] HRESULT LoginUser([in] BSTR sUserName, [in] BSTR sPassword, [out, retval] IDispatch ** pResult);
[propget, id(2), helpstring("property m_nUserID")] HRESULT m_nUserID([out, retval] ULONG* pVal);
[propget, id(3), helpstring("property m_nUserRightsMask")] HRESULT m_nUserRightsMask([out, retval] ULONG* pVal);
[propget, id(4), helpstring("property SetPassword")] HRESULT SetPassword([in] BSTR sPassword, [in,optional] VARIANT nUserID, [out, retval] IDispatch ** pResult);
[propget, id(6), helpstring("property VerifyLdapCredentials")] HRESULT VerifyLdapCredentials([in]BSTR sUserName, [in]BSTR sPassword, [in]BSTR sLdapServer,[in]ULONG nLdapPort,[in]BSTR sAuthorizeDn,[in]VARIANT_BOOL bSecure, [out, retval] IDispatch ** pResult);
[propget, id(7), helpstring("property CreateUser")] HRESULT CreateUser([in] BSTR sUserName, [in] BSTR sPassword, [in]ULONG nUserRightsMask, [in] ULONG nAuthenticationType, [in] ULONG nHomeGroupID, [in] ULONG nLanguageID, [out, retval] IDispatch** pVal);
[propget, id(8), helpstring("property m_nLanguageID")] HRESULT m_nLanguageID([out, retval] ULONG* pVal);
};
最后,这是coclass的定义:
[
uuid(BF748C0A-450D-4EAF-8C39-A36F6B455587),
helpstring("ComUser Class")
]
coclass ComUser
{
[default] interface IComUser;
};
我该怎么办?
编辑:我应该提到我最初没有使用命名参数;我只是努力使错误消失。
答案 0 :(得分:13)
嗯,你的代码建议你实际使用C#4.0,因为你使用的是命名参数。该版本支持COM互操作方案中的索引属性。然而,索引器语法需要[方括号]。不知道它是否仍然适用于多个参数,这些例子都只有一个。先试试这个:
var result = userObject.LoginUser["foo", "bar"];
或解决问题:
var result = userObject.get_LoginUser("foo", "bar");
请告诉我们您的结果,我有兴趣了解是否支持具有多个参数的索引属性。