In the book Dependency Injection in .NET, the author says that Spring.NET doesn't support creation of custom object lifetimes (See last paragraph of section 12.2 [Managing lifetime]).
Even though I am new to the framework, I think this may not be the case. Based on my research so far, I think one can define custom lifetimes by implementing the ITargetSource interface, though, arguably, this interface can do much more than that (like some predefined implementations include object pooling and hot-swappable targets etc.).
Is my understanding correct? If yes, what are the exact logical steps for creating AND configuring a custom lifetime? If no, how does one create a custom object lifetime in Spring.NET?
Ok, so I actually asked another question here and seems like answered this very question in the process (this is one of those rare occasions where you answer two of your own questions with one answer posted by yourself). If you follow that other question, you'll see that it's indeed possible to define custom life times in Spring.NET.
So in summary, a custom lifetime in Spring.NET can be created by implementing the ITargetSource interface, though, arguably, it's a subtle interface and can be used to do fancy things around creating targets. There are already few implementations available including (but not limited to):
SingletonTargetSource (provides the singleton lifetime)
PrototypeTargetSource (provides the transient lifetime)
ThreadLocalTargetSource (provides thread-scoped lifetime)
SimplePoolTargetSource (provides object pooling)
HotSwappableTargetSource (provides the capability to swap targets at runtime)
Interestingly, applying a lifetime to your objects can be very different depending on what lifetime you want. All objects in Spring.NET are singleton by default. To specify an object as prototype (Spring.NET speak for transient), you set singleton="false" as follows:
<object id="..." type="..." singleton="false"/>
Unfortunately, there's no such convenient property for the rest of the provided lifetimes (including your custom implementations). So, let's say you want to configure an object with thread-local scope. Here's how you'd do that using ProxyFactoryObject:
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net">
<object id="ConsoleLoggingBeforeAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice"/>
</property>
</object>
<object id="ServiceCommandTargetSource" type="Spring.Aop.Target.ThreadLocalTargetSource">
<property name="TargetObjectName" value="ServiceCommandTarget"/>
</object>
<object id="ServiceCommandTarget" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object name="ServiceCommand" type="Spring.Aop.Framework.ProxyFactoryObject">
<property name="TargetSource" ref="ServiceCommandTargetSource"/>
<property name="InterceptorNames">
<list>
<value>ConsoleLoggingBeforeAdvisor</value>
</list>
</property>
</object>
</objects>
Again, if you want to achieve the exact same results as the above configuration but using DefaultAdvisorAutoProxyCreator, you'll have to do it in an entirely different way, including implementing a custom type that implements the ITargetSourceCreator interface.
Here's a bare bone ITargetSourceCreator implementation that creates a ThreadLocalTargetSourceCreator:
namespace Spring.Examples.AopQuickStart {
public class ThreadLocalTargetSourceCreator : AbstractPrototypeTargetSourceCreator, ITargetSourceCreator {
private readonly ThreadLocalTargetSource _threadLocalTargetSource;
public ThreadLocalTargetSourceCreator() {
_threadLocalTargetSource = new ThreadLocalTargetSource();
}
protected override AbstractPrototypeTargetSource CreatePrototypeTargetSource(Type objectType, string name, IObjectFactory factory) {
return _threadLocalTargetSource;
}
}
}
Finally, you need to use the following configuration to use the above ITargetSourceCreator with DefaultAdvisorAutoProxyCreator to create instances of your target type at thread-local scope:
<?xml version="1.0" encoding="utf-8"?>
<objects xmlns="http://www.springframework.net" default-autowire="constructor">
<object id="ConsoleLoggingBeforeAdvice" type="Spring.Aop.Support.DefaultPointcutAdvisor">
<property name="Advice">
<object type="Spring.Examples.AopQuickStart.ConsoleLoggingBeforeAdvice" />
</property>
</object>
<object id="ServiceCommand" type="Spring.Examples.AopQuickStart.ServiceCommand" singleton="false"/>
<object type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator">
<property name="CustomTargetSourceCreators">
<list element-type="Spring.Aop.Framework.AutoProxy.ITargetSourceCreator">
<object type="Spring.Examples.AopQuickStart.ThreadLocalTargetSourceCreator"/>
</list>
</property>
</object>
</objects>
In my opinion, the way you configure lifetimes other than singleton (default) and prototype is somewhat non-intuitive and definitely not streamlined across different types of proxy factory implementations (ProxyFactoryObject vs. DefaultAdvisorAutoProxyCreator)
In summary, yes, Spring.NET does support custom lifetimes. If none of the predefined lifetimes meet your requirements, you can create a custom lifetime by implementing the ITargetSource interface and configuring it appropriately.
Related
I would like to have a C++ client application that maintains a cache of objects that come from a Java server. The objects need to be compatible. I understand that Gemfire maintains them in a serializable format. This means the Java class needs to be equivalent to the C++ class.
Is there a common practice for defining the class structure in common place in a language-independent specifcation and generating the equivalent Java and C++ classes that are serializable to PDX or any other form that Gemfire uses?
Regards,
Yash
Before PDX I used to create a language-neutral representation of my domain and simultaneously generate Java, C++ and .Net classes using DataSerializable. However, PDX makes this unnecessary for the most part. I enclose the sample config below.
If you encounter types that you are using that Java does not support, you still do not have to resort to generating serializers but you can focus in on serializing that one type (see page 564 of http://gemfire.docs.pivotal.io/pdf/pivotal-gemfire-ug.pdf
Consider generating your own serializers when you have an insane need for speed since the auto-serializer can produce a drag. This is usually not needed but if you do, here are the instructions: http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/DataSerializer.html
Here is the configuration for using the pdx auto serializer:
<!-- Cache configuration configuring auto serialization behavior -->
<cache>
<pdx>
<pdx-serializer>
<class-name>com.gemstone.gemfire.pdx.ReflectionBasedAutoSerializer
</class-name>
<parameter name="classes">
<string>com.company.domain.DomainObject</string>
</parameter>
</pdx-serializer>
</pdx>
...
</cache>
If I answered your question, please give check "Answered". Thanks.
Is there a way I can call static methods from blueprint. As per the aries blueprint documentation I can use static functions to create objects, but I could not find if I could do it for classes which offer static functions to do some functionality.
Thanks
Lalit
Example from this page:
<bean id="current-time" class="java.lang.System" factory-method="currentTimeMillis" scope="prototype"/>
I'm engaged in building NServiceBus Gateway handler, and I need to avoid config files so that all configuration is defined inside c# classes. As a result I have to convert the following section to c# code
<GatewayConfig>
<Channels>
<Channel Address="http://localhost:25899/SiteB/" ChannelType="Http" Default="true"/>
</Channels>
</GatewayConfig>
I've found GatewayConfig, ChannelCollection and ChannelConfig in a NServiceBus.Config namespace, but I can not link them together, coz GatewayConfig refers to ChannelCollection, but ChannelCollection has nothing to do with ChannelConfig. Please help
Just create a class implementing IProvideConfiguration of GatewayConfig. That gives you a way to provide your own config. Look at the pubsub sample for the exact details on how to do this.
Well, I've found the way to do it as I installed Reflector and looked into the implementation. There is a ChannelCollection.CreateNewElement() method returning back System.Configuration.ConfigurationElement. NServiceBus overriden the method instantiating ChannelConfig inside it, so all I have to do is to cast ConfigurationElement type to ChannelConfig type which is far from intuitive interface. Looks like this NServiceBus.Config.ChannelCollection is kind of unfinished work, because if you look at other collections like NServiceBus.Config.MessageEndpointMappingCollection you can find there all necessary type-safe methods to work with its child elements NServiceBus.Config.MessageEndpointMapping, so I think NServiceBus team was just lazy to make the same for ChannelCollection.
UPDATE: as CreateNewElement() method is protected, I have to implement my own class inherited from ChannelCollection to make a method adding new ChannelConfig element publicly available
in My nhibernate.cfg.xml file I have
<mapping assembly="X.Domain" />
Which would usually works - Inside My X.Domain I have my Fluent Mappings. in which I have tests to verify all the mappings are set up correctly. Not sure if this is because I am using Fluent in my Domain Layer and nhiberante.cfg.xml in my MVC project.
Any ideas
The <mapping/> element is part of NH core; it only recognizes hbm.xml files built as embedded resources, not fluent mappings.
I needed a way to trim strings within my persistent class because my legacy database is using char fields. I downloaded the nHhaddIns dll to use its TrimString class which is derived from IUserType.
Using their example I created a property in my mapping class as shown at the bottom.
uNHAddIns is added as a project within my solution. However, I received this error:"Could not determine type for: uNhAddIns.UserTypes.TrimString, uNhAddIns, for columns: NHibernate.Mapping.Column(HSTAT)"
I tried running the example that is in the uNhAddIns project and receive the same error. Any ideas?
<property name="HSTAT" column="HSTAT" type="uNhAddIns.UserTypes.TrimString, uNhAddIns" />
Don't know if you've managed to fix this already, but does your own uNhAddIns.UserTypes.TrimString inherit from IUserType? My own pattern for user types in NHibernate involves the type implementation living in the DataModel, and the required IUserType interface living separately in my DataAccess layer. The IUserType implementation does the necessary marshalling between the database and my DataModel type implementation.
I just came across this same error when trying to use the DataModel class in my mapping file rather than the IUserType implementation.