almightylinuxgod

Hello All,

I have an interesting idea to increace productivity on a project of mine. My hope is to be able to create an instance of a C# component through the CCW using standard ComVisible techniques. That all works fine. Once the object is instanciated, it creates a Dynamic Type in a Dynamic Assembly and returns it to the host. This also works fine. The problem is that the in memory instance does not properly impliment IDispatch to VBScript is not able to make calls on it. Is there any way to override the stanard IDispatch of the CLR Or better yet, can I get the type to "just work"

Code Snippet

[ComVisible(true)]

[Guid("0EC51F67-0426-495b-B2C2-06515EB63DE0")]

[ClassInterface(ClassInterfaceType.AutoDual)]

[ProgId("DirectorsDesk.ConfigurationServiceRuntimeAgent")]

public class ConfigurationServiceRuntimeAgent

{

bool _isAspCalled = false;

Server _aspServer;

public ConfigurationServiceRuntimeAgent()

{

object serverObject = ContextUtil.GetNamedProperty("Server");

if ((serverObject != null) && (serverObject is Server))

{

_isAspCalled = true;

_aspServer = serverObject as Server;

Response aspResponse = ContextUtil.GetNamedProperty("Response") as Response;

aspResponse.Write("This comes from .NET!");

}

}

public object Stub()

{

AppDomain currentAppDomain = AppDomain.CurrentDomain;

AssemblyName dynamicName = new AssemblyName("DynamicAssemblyDD");

AssemblyBuilder assemblyBuilder = currentAppDomain.DefineDynamicAssembly(dynamicName, AssemblyBuilderAccess.RunAndSave);

ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("DynamicAssemblyDD.dll", "DynamicAssemblyDD.dll");

TypeBuilder typeBuilder = moduleBuilder.DefineType("CompanyConfigurationType", TypeAttributes.Public);

typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

ConstructorInfo clsI = typeof(ClassInterfaceAttribute).GetConstructor(new Type[] { typeof(ClassInterfaceType) });

typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(clsI, new object[] { ClassInterfaceType.AutoDual }));

ConstructorInfo cvType = typeof(ComVisibleAttribute).GetConstructors()[0];

typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(cvType, new object[] { true }));

MethodBuilder getExValueMethod = typeBuilder.DefineMethod("GetExValue", MethodAttributes.Public, typeof(string), null);

ILGenerator ilGenerator = getExValueMethod.GetILGenerator();

Label brS = ilGenerator.DefineLabel();

ilGenerator.DeclareLocal(typeof(string));

ilGenerator.Emit(OpCodes.Nop);

ilGenerator.Emit(OpCodes.Ldstr, "Hello World!");

ilGenerator.Emit(OpCodes.Stloc_0);

ilGenerator.Emit(OpCodes.Br_S, brS);

ilGenerator.MarkLabel(brS);

ilGenerator.Emit(OpCodes.Ldloc_0);

ilGenerator.Emit(OpCodes.Ret);

Type resultType = typeBuilder.CreateType();

assemblyBuilder.Save(@"DynAssembly.dll");

return Activator.CreateInstance(resultType);

}

public string StubUsed()

{

object stubObject = Stub();

Type stubObjectType = stubObject.GetType();

return (string)stubObjectType.InvokeMember("GetExValue", BindingFlags.InvokeMethod, Type.DefaultBinder, stubObject, null);

}

}

This is an example client

Code Snippet

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title></< FONT>title>

</< FONT>head>

<body>

<script runat="server" language="vbscript">

' VBScript File

Set oClient = Server.CreateObject("DirectorsDesk.ConfigurationServiceRuntimeAgent")

Response.Write(oClient.StubUsed())

Set oGen = oClient.Stub()

Response.Write(oGen.GetExValue())

</< FONT><script>

</< FONT>body>

</< FONT>html>

The call to StubUsed works, as .NET can reflect and late call the method, but the call to GetExValue() directly does not work.


Re: Common Language Runtime Dynamic Assemblies unable to IDispatch

Feng Chen - MSFT

Hi almightylinuxgod,

And I'm not sure about what you mean by " the call to GetExValue() directly does not work", could you please clarify

Thanks!






Re: Common Language Runtime Dynamic Assemblies unable to IDispatch

almightylinuxgod

Code Snippet

Response.Write(oClient.StubUsed())



This line provides the expected result because the late binding call is performed in .NET


Code Snippet

Response.Write(oGen.GetExValue())



This line does not work because the late binding call is performed on COM and IDispatch in VBScript





Re: Common Language Runtime Dynamic Assemblies unable to IDispatch

Feng Chen - MSFT

Hi almightylinuxgod,

I'm still not sure about what you mean by "does not work" Exception Crash Compling error We can troubleshoot this issue as long as you can clarify.

Thanks for your understanding!






Re: Common Language Runtime Dynamic Assemblies unable to IDispatch

almightylinuxgod

Microsoft VBScript runtime error '800a01b6'

Object doesn't support this property or method: 'GetExValue'

/Default.asp, line 13





Re: Common Language Runtime Dynamic Assemblies unable to IDispatch

Feng Chen - MSFT

Hi almightylinuxgod,

You can try to change your C# code like this:

Code Snippet

typeBuilder.SetCustomAttribute(new CustomAttributeBuilder(clsI, new object[] { ClassInterfaceType.None}));

This enum value "Indicates that no class interface is generated for the class. If no interfaces are implemented explicitly, the class can only provide late bound access through the IDispatch interface. This is the recommended setting for ClassInterfaceAttribute. Using ClassInterfaceType.None is the only way to expose functionality through interfaces implemented explicitly by the class."

For more details, please visit: ClassInterfaceType Enumeration and Do not use AutoDual ClassInterfaceType.

Hope this helps!

Thanks!