View Full Version : Programatic Add of an Object to a Context?
sbellware
01-13-2006, 09:41 PM
Hi all,
Is there a way to instantiate a context, and then add a pre-existing instance of an object to it along with an ID so that it can be returned from the context by CreateObject()?
-Scott
Aleks Seovic
01-14-2006, 07:11 AM
Of course, it's relatively easy -- all you need to do is cast your context instance to IConfigurableApplicationContext, which will give you access to the underlying object factory that you need to register object with:
((IConfigurableApplicationContext) applicationContext).ObjectFactory.RegisterSingleto n("MyObjectId", myObject);
Keep in mind that this will work, as the method name says, only for singletons. If you need to add a prototype programatically it is possible but a bit more involved, as you need to create the whole object definition for it and add definition to object factory.
HTH,
Aleks
sbellware
01-15-2006, 07:07 AM
Hi Aleks. Thanks for the response.
I think I could probably get away with using the singleton, but I'd be interested in investigating what's involved in doing this for a prototype. If you could point me in the direction of the topics that I need to take a look at, it'd be much apppreciated.
-Scott
Aleks Seovic
01-16-2006, 03:38 AM
Hi Scott,
I'm not sure this topic is much documented, mostly because it's fairly advanced usage scenario that shouldn't be necessary for most applications. Our recommendation is to simply configure all the objects you need within the context and use programmatic registration only for special cases.
That said, I'll try to describe the steps necessary to create object definitions programatically and register them with the application context. This approach will allow you to create definitions for both singletons and prototypes, but as I mentioned in the previous post, the easiest way to register existing singleton instance is to use RegisterSingleton method instead.
There are several steps that are required to create and register object definition:
1. Create an instance of IObjectDefinitionFactory. Typically you will create an instance of DefaultObjectDefinitionFactory, but if you are writing web application you should use WebObjectDefinitionFactory instead, which adds support for Scope property and ASP.NET pages.
2. Create instances of ConstructorArgumentValues and/or MutablePropertyValues, depending on whether you want to use constructor or property injection, and add desired properties and constructor arguments to them.
3. Call IObjectDefinitionFactory.CreateObjectDefinition method, passing type name, parent object's id (if any), constructor arguments, property values and app domain that should be used to resolve types as arguments.
4. Set additional properties on the created IObjectDefinition instance, such as IsSinleton, IsLazyInit, etc.
5. Obtain a reference to IObjectDefinitionRegistry by casting application context's object factory and register object definition with it.
Here is the sample code that demonstrates the steps described above:
IObjectDefinitionFactory factory = new DefaultObjectDefinitionFactory();
ConstructorArgumentValues constructorArgs = new ConstructorArgumentValues();
constructorArgs.AddNamedArgumentValue("arg1", "MyStringValue");
constructorArgs.AddNamedArgumentValue("arg2", myObjectValue);
MutablePropertyValues properties = new MutablePropertyValues();
properties.Add("myStringProperty", "MySecondStringValue");
properties.Add("myArrayProperty", new object[] {...});
properties.Add("myReferenceProperty", new RuntimeObjectReference("objectId"));
IObjectDefinition objDef = factory.CreateObjectDefinition("MyCompany.MyObjectType, MyAssembly", null, constructorArgs, properties, AppDomain.CurrentDomain);
objDef.IsSingleton = true; // set this to false for prototype definition
objDef.IsLazyInit = true;
IObjectFactory objectFactory = ((IConfigurableApplicationContext) applicationContext).ObjectFactory;
((IObjectDefinitionRegistry) objectFactory).RegisterObjectDefinition("myObjectId", objDef);
I guess that should be enough to get you started. Keep in mind that both property and constructor args accept many things in addition to specific object values. For example, I used RuntimeObjectReference in one of the examples, but there are also things such as ManagedList, ManagedMap, etc., that can contain nested object definitions in addition to regular objects.
If you want to see more realistic sample code, take a look at one of the configuration parsers to see how they work. Standard parser is fairly complex and intimidating, so my advice is to start with one of the simpler custom parsers, such as ValidationConfigParser, for example.
Regards,
Aleks
sbellware
01-16-2006, 06:50 AM
Thanks, Aleks! Much appreciated!
-Scott
De Fille
06-12-2006, 10:38 AM
Hi folks,
I'm a newbie and i'm trying to add programmatic an object.
I get no errors but the object doesn't get added to my file.
What i'm a doing wrong?
my app.config
<configSections>
<sectionGroup name="spring">
<section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core"/>
</sectionGroup>
</configSections>
<spring>
<context>
<resource uri="file://spring.xml"/>
</context>
</spring>
my spring.xml
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<object id="test" type="Springtest.Testclass, Springtest">
<constructor-arg name="ID" value="2"/>
</object>
</objects>
my code
Public Sub Register(ByVal typeID As Guid, ByVal o As Object)
Dim factory As IObjectDefinitionFactory = New DefaultObjectDefinitionFactory
Dim constructorArgs As New Spring.Objects.Factory.Config.ConstructorArgumentV alues
constructorArgs.AddNamedArgumentValue("ID", typeID)
Dim objDef As Config.IObjectDefinition = factory.CreateObjectDefinition(o.GetType().ToStrin g & "," & o.GetType().Assembly.ToString, Nothing, constructorArgs, Nothing, AppDomain.CurrentDomain)
Dim context As IApplicationContext = ContextRegistry.GetContext()
Dim objFactory As IObjectFactory = CType(context, IConfigurableApplicationContext).ObjectFactory
CType(objFactory, IObjectDefinitionRegistry).RegisterObjectDefinitio n(o.GetType().ToString, objDef)
End Sub
If you could help me solve this plz.
Filip
Bruno Baia
06-13-2006, 09:51 AM
Hi,
You can use IConfigurableApplicationContext.RegisterSingleton to register a singleton under a given name :
IApplicationContext ctx = ContextRegistry.GetContext();
((IConfigurableApplicationContext)ctx).ObjectFacto ry.RegisterSingleton("myTestObject", new TestObject());
If it's not enought for what you want to do, you can to do something more complex as shown in this topic.
Your code seems oki, have you tried to see if the object has been registered using GetObjectDefinitionNames method ?
IApplicationContext ctx = ContextRegistry.GetContext();
ctx.GetObjectDefinitionNames();
-Bruno
De Fille
06-13-2006, 10:20 AM
Hi,
It seems it actually gets added to the context. But it doesn't get saved in my "spring.xml" document. I'm a missing something in my app.config or do i need to restart or save something..?
Filip
De Fille,
It won't get saved into xml. The code shown by Bruno is just a way you can register a singleton object programmatically.
De Fille
06-13-2006, 07:44 PM
Hi,
So there isn't a way to save it into your xml file, except creating your own xmlnodes for you xmldocument and then save it?
Filip
Bruno Baia
06-19-2006, 03:49 PM
Yep.
Then you also need to refresh manually the application context.
-Bruno
vBulletin® v3.7.3, Copyright ©2000-2008, Jelsoft Enterprises Ltd.