Joe Mamma Posted July 5, 2004 Posted July 5, 2004 ok, here's the situation. I am trying to write a class (DynamicServiceFactory) that creates a dynamic assembly ("DynamicService.dll") which contains a dynamic module that defines an ObjectPooling Attributed type ("DynamicServicedComponent"), deriving from Windows.Enterprise.Services.ServicedComponent, where the "CreationTimeout", "MaxPoolSize" and "MinPoolSize" poperties are set at runtime. The point is, during initialization, I want the DynamicServiceFactory to configure how many instances of DynamicServicedComponents are allowed to run in the Machines Pooled Object environment. I would then get a Pooled object by calling DynamicServiceFactory.GetDynamicServicedComponent() This should instance a DynamicServicedComponent Type from the dynamically created assembly. (Does any of this make sense???) the problem is this always returns null. . . no exception thrown just a null public ServicedComponent GetDynamicServicedComponent() { return (ServicedComponent) m_Assembly.CreateInstance("DynamicServicedComponent"); } I have a feeling there is a problem in my TypeBuilder usage as I cant see any namespaces or types in the saved assembly. any ideas??? Here is my complete code: using System; using System.EnterpriseServices; using System.Reflection; using System.Reflection.Emit; using System.IO; namespace DynamicServer { public class DynamicServiceFactory { Assembly m_Assembly; private void CreateDynamicServicedComponentType(int MinObjects, int MaxObjects, int CreationTimeout) { // This should basically create an assembly containing the following simple class definition: // [ ObjectPooling( MinPoolSize= [MinObjects] , // MaxPoolSize= [MaxObjects], // CreationTimeout= [CreationTimeout], // Enabled = true ) ] // public class DynamicServicedComponent: ServicedComponent {} // // Get the domain AppDomain myDomain = System.Threading.Thread.GetDomain(); // Load a strong name key pair needed for serviced component assemblies FileStream fs = new FileStream("dynclass.snk", FileMode.Open); StrongNameKeyPair kp = new StrongNameKeyPair(fs); fs.Close(); // Set up the assembly AssemblyName myAsmName = new AssemblyName(); myAsmName.Name = "DynamicService.dll"; myAsmName.KeyPair = kp; AssemblyBuilder myAsmBuilder = myDomain.DefineDynamicAssembly( myAsmName, AssemblyBuilderAccess.RunAndSave); // Define the dynamic module ModuleBuilder ServicedComponentModule = myAsmBuilder.DefineDynamicModule("DynamicServicedComponent", true); // Define the dynamic type derived from Serviced Component TypeBuilder ServicedComponentBuilder = ServicedComponentModule.DefineType( "DynamicServicedComponent", TypeAttributes.Public , typeof(ServicedComponent) ); // Get a constructor for an ObjectPoolingAttribute Type[] ctorParams = new Type[] {}; ConstructorInfo classCtorInfo = typeof(ObjectPoolingAttribute).GetConstructor(ctorParams); // Build the ObjectPoolingAttribute Properties Type myType = typeof(ObjectPoolingAttribute); System.Reflection.PropertyInfo[] myProps = new System.Reflection.PropertyInfo[] { myType.GetProperty("CreationTimeout"), myType.GetProperty("Enabled"), myType.GetProperty("MaxPoolSize"), myType.GetProperty("MinPoolSize") }; // Build the ObjectPoolingAttribute Property Values object[] propVals = new object[] { CreationTimeout,true, MaxObjects, MinObjects}; // Use a CustomAttributeBuilder to construct the ObjectPoolingAttribute and set the properties CustomAttributeBuilder myCABuilder = new CustomAttributeBuilder classCtorInfo, new object[]{} , myProps, propVals); // Apply the ObjectPoolingAttribute to the Dynamic Type ServicedComponentBuilder.SetCustomAttribute(myCABuilder); // Create the type in the assembly ServicedComponentBuilder.CreateType(); // Save the Assembly Builder Contents to disk myAsmBuilder.Save(myAsmName.Name); m_Assembly = Assembly.LoadFile(Path.GetFullPath(".")+ @"\DynamicService.dll"); } // Constructor initializes a DynamicService Type with ObjectPooling attribute configured and enabled public DynamicServiceFactory(int MinObjects, int MaxObjects, int CreationTimeout) { CreateDynamicServicedComponentType(MinObjects, MaxObjects, CreationTimeout); } // This should instance a DynamicService public ServicedComponent GetDynamicServicedComponent() { return (ServicedComponent) m_Assembly.CreateInstance("DynamicServicedComponent"); } } } please help. . . thanks Quote Joe Mamma Amendment 4: The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no warrants shall issue, but upon probable cause, supported by oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized. Amendment 9: The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.
Joe Mamma Posted July 5, 2004 Author Posted July 5, 2004 oh yeah. . . I tried this, in the creation of the dynamic module (just to see what would happen), but it throws a weird error: Type type = ServicedComponentBuilder.CreateType(); Type[] types = new Type[0]; ConstructorInfo ci = type.GetConstructor(types); object o = ci.Invoke(types); with an error: The invoked member is not supported in a dynamic module. Quote Joe Mamma Amendment 4: The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no warrants shall issue, but upon probable cause, supported by oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized. Amendment 9: The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.
Administrators PlausiblyDamp Posted July 6, 2004 Administrators Posted July 6, 2004 Not played with dynamic assemblies much but stepping through your code everything appears to be working apart from the .dll that is generated doesn't contain any types. If you open it with ildasm then it has a valid manifest but nothing else. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Joe Mamma Posted July 6, 2004 Author Posted July 6, 2004 Not played with dynamic assemblies much but stepping through your code everything appears to be working apart from the .dll that is generated doesn't contain any types. If you open it with ildasm then it has a valid manifest but nothing else.Yeah I noticed that too. . . but I am calling TypeBuilder.CreateType() If I change DefineType to inherite from typeof(object) (removing the custom attribute application) the assembly works even though ildasm still shows no types in it. I even took the examples out of Help and they dont show any types in the dynamic assembly the example generates either. . . but. . . if I change the DefineDynamicModule to: ModuleBuilder ServicedComponentModule = myAsmBuilder.DefineDynamicModule("DynamicServicedComponent","DynamicServicedComponent.mod", true); the manifest does show this, even thought the assembly doesnt show the class: .class extern /*27000001*/ public 'DynamicService.DynamicServicedComponent' { .file 'DynamicServicedComponent.mod'/*26000001*/ .class 0x02000002 } I can open the .mod file in ildasm and that shows the class. Quote Joe Mamma Amendment 4: The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no warrants shall issue, but upon probable cause, supported by oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized. Amendment 9: The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.
Administrators PlausiblyDamp Posted July 6, 2004 Administrators Posted July 6, 2004 I suppose that's the point of a dynamic assembly - there is no code persisted only enough of the manifest to allow the LoadFile to work. Been having a look at this on and off all day and I just can't figure out why it won't work as your code stands. It just doesn't seem to emit the type when you do the save. Strange thin gis calling .GetTypes() on the myAsmBuilder will return an array of 1 type, calling the same on m_Assembly doesn't. It feels there should be an easier way to go from an AssemblyBuilder to an assembly rather than having to try and reload it. Quote Posting Guidelines FAQ Post Formatting Intellectuals solve problems; geniuses prevent them. -- Albert Einstein
Joe Mamma Posted July 6, 2004 Author Posted July 6, 2004 Yeah I actually posted one of my many attempts at getting this to work. I have been able to get the general types out of the assembly builder without reloading the assembly. I even get the ServicedComponent Type out of the assembly builder. The only problem is with anything derived from ServicedComponent, invoking the constructor fails with the error message described about being unable to invoke out of dynamic module. Now. . . the question is, is there something on ServicedComponent that prevents it from being dynamically derived for security reasons? I could understand that being the case (I mean you wouldnt want some assembly creating a stealth service on your machine, now would you?), but I would imagine there would be some hoops to jump through to get it done. I can't find any documentation that elaborates on the enterprise services beyond that which is in the help. this leads me to beieve that this situation may just be a bug. At any rate, thank you for the sanity check. much obliged. Pretty neat concept though, eh? The purpose is to give some rudimentary licensing capability to an enterprise application. IE, sell a server that will only allow x amount of DynamiceServicedComponents to be instanced at a time without haveing to recompile a server for each of our customers. just send them an encrypted license file, save to their system and restart the server. If I get it to work I will keep the site posted. Again , thank you for the sanity check!!! Really!!! I just might sleep tonight! Quote Joe Mamma Amendment 4: The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no warrants shall issue, but upon probable cause, supported by oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized. Amendment 9: The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.
Joe Mamma Posted July 9, 2004 Author Posted July 9, 2004 (edited) Problem Solved!!! Imagine this. I got a quick, definitive and FREE (Imagine that!!!) response from support.microsoft.com After the DefineType call, I needed to add: ServicedComponentBuilder.DefineDefaultConstructor(MethodAttributes.Public); Funny, the help file said I only needed to do that if I was adding attributes to the default constructor of the base type. The default constructor was already public. hmmm. . . Maybe there is a bug in or simply a lack of documentation on ServicedComponent. As soon as I have this complete, I will post the solution as I think some might find the class handy. What it is is a remotable object where the host application can dynamically configure at runtime the max number of objects that can be pooled in enterprise services. Typically, object pooling is a compile time setting. This would make a developer compile a unique executable for each customer in his customer base. By dynamically configuring this, one can distribute a common host application with a customer specific license file to control authorized usage of an application. Next, it will have a function that when the host app starts it will broadcast its presence on its subnet and only start if it doesn't get a response back from any other servers within a specified timeout period. At the same time, it will listen from broadcasts from other instances and respond back to them so they wont start. I've yet to find any other solutions that don't cost alot of money. If anyone has any ideas, please pass them on. I know, its very rudimentary, as a savvy sysop could get around it, but definitely a step up from just giving them a setup and telling them not to install it more than once. comments? ideas??? thanks Edited July 9, 2004 by Joe Mamma Quote Joe Mamma Amendment 4: The right of the people to be secure in their persons, houses, papers, and effects, against unreasonable searches and seizures, shall not be violated, and no warrants shall issue, but upon probable cause, supported by oath or affirmation, and particularly describing the place to be searched, and the persons or things to be seized. Amendment 9: The enumeration in the Constitution, of certain rights, shall not be construed to deny or disparage others retained by the people.
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.