I'm having a problem with a component in my container with a Transient lifestyle. The first time I call resolve, I hit the constructor of the implementation type as expected.
However, the second time I call resolve, a new instance is not constructed. Rather, the existing instance is reused. I don't think this should happen, since my component's LifestyleType is set to Transient (I have verified this at runtime in debugging mode at a breakpoint):
Kernel.GetAssignableHandlers(typeof(object))[33].ComponentModel.LifestyleType
// 33 is the verified index of my component type...this returns Transient as expected
At the same breakpoint, I have run the following in the immediate window and verified that a new instance is not constructed:
Resolve(Kernel.GetAssignableHandlers(typeof(object))[33].Service)
// this does NOT return a new instance!
// ...It returns the same instance from the first time Resolve was called.
// I can tell by the state of the object and because the constructor on the object is not called.
Update:
I've narrowed the problem down, I think.
The below test fails:
var container = new WindsorContainer();
container.Kernel.AddComponent<MyLazyComponentLoader>(typeof (ILazyComponentLoader));
var instance1 = container.Resolve<MyClass>();
var instance2 = container.Resolve<MyClass>();
Assert.AreNotSame(instance1, instance2);
MyLazyComponentLoader simply returns
Component.For(service)
which is defaulting to Singleton LifestyleType (even though it shows up as Unknown on the ComponentModel. Is this by design?
Thanks.
Per Krzysztof Koźmic: Yes, the default lifestyle is singleton, Unknown means it's not specified explicitly, but Windsor treats it as if you specified Singleton. If you want it to be transient, be explicit.
Related
How DbMigrator works
I have code that instantiates a new DbMigrator(new Configuration())
Configuration is a custom extension of DbMigrationsConfiguration<T>, where T is DbContext
So within Configuration, there is a ContextType, which is equal to <T>.
When DbMigrator is instantiated, it attempts to create an instance of the <T> DbContext. It will either try to use an Empty Constructor on the <T> Context, or it will attempt to look for an implementation of IDbContextFactory<...> where ... is the actual type of , but not generic T.
How DbMigrator Doesn't Work
The problem is, the assembly instantiating DbMigrator has no access to the specific typed IDbContextFactory<...> that it needs to discover. Also, my DbContext has no default constructor, and I don't want it to. So I receive the exception The target context '...' is not constructible.
The thing that bothers me is, at the point I am instantiating DbMigrator, I already have an instance (or may already be within an instance) of the DbContext I am migrating. Also, I have access to a generic IDbContextFactory<T> that is not discoverable by DbMigrator's internals, but I'd be happy to provide it an instance.
The Question
So how do I tell DbMigrator to either just use my Context instance, or use an instance of a IDbContextFactory I specify? When it relies on its magic juju behind the scenes to try to discover these things (presumably using reflection/ServiceLocation) it is failing.
My Situation
Within one AppDomain, I am using n Contexts. I'd like to say one, but it's typically two, and may be more than that. So any solution that relies on a single app/web config property, or an attribute decorator, which points to a single DbConfiguration or ConnectionFactory won't work for me. Because there can only be one per AppDomain and, unless I could configure it based contextually on which Context I'm needing at the time, it is futile. So there's wiggle room there, but I dunno.
Also, there may be some juju I don't understand about EF relating to the base constructor. But I don't believe passing a DbConnection into the constructor instead of a nameOrConnectionString would work. It is still not an empty constructor. But if there's something EF does to search for constructors with that, and how to utilize it, that MIGHT work.
I want to fix a design flaw in a record TMyValue that has been in use for years, and I desperately want to fix it in the record itself - to avoid changing the public interface - and not require the code using the record to be changed.
Essentially, the flaw is that a TMyValue must be initialised to zero when it is created, otherwise calling the Clear method on it can cause a crash. This is because it contains a field that is a pointer to dynamically-allocated memory if the pointer is non-nil, and Clear causes the dynamic memory to be freed.
This is a problem if the TMyValue is created on the stack, because stack variables are not zeroed out automatically when they are created.
I thought I could use a record constructor to zero out the record, but record constructors cannot be parameterless. Presumably this means that you cannot force a record constructor to be executed automatically when a record is created on the stack.
I suspect the answer to my question is "it cannot be done". Please prove me wrong!
Add a dummy string member into your record.
Since a string is a managed type it will be initialized to an empty string when the record comes in scope.
So when calling your Clear method, test if the dummy string is empty first.
Set the string to a value when appropriate to the use logic to mark the record as initialized.
When I bind my context as InRequestScope, the context is disposed when the code in DelegatingHandler is called (instantiated in Application_Start and executed before controllers are initialized). If I use InTransientScope, then it works but I want 1 context for everything. Based on this answer here, it is the correct way to have 1 context.
Global.asax
static void Configure(HttpConfiguration config)
{
var kernel = NinjectWebCommon.Bootstrapper.Kernel;
config.MessageHandlers.Add(new ApiKeyHandler(kernel.Get<IApiService>()));
}
Bindings
//if i remove InRequestScope here, everything works.
kernel.Bind<EntityDatabaseContext>().ToMethod(context => new EntityDatabaseContext()).InRequestScope();
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
//repositories
kernel.Bind<IRepository<Application>>().To<Repository<Application>>().InRequestScope();
//services
kernel.Bind<IApiService>().To<ApiService>().InRequestScope();
So Whenever SendAsync gets called in ApiKeyHandler, the context was already disposed. But when a controller is called (after calling the ApiKeyHandler), the context is fine. I'm not too sure what is going on. If it cannot work with InRequestScope, how can I accomplish it like how the answer in the linked question did it? 1 context InTransientScope and all others in InRequestScope?
Using a transient or singleton scoped context for your message handler gives you the limitation that all the entities will be cached for the message handler. E.g. if an entity is changed/deleted or a new one is added your message handler will never adapt to that change. This can be ok in some scenarios where the data is never changed.
If you need to operate on up to date data that will change you can't use these scopes. But InRequestScope means that you have to create a new instance of the service every time using a factory (see factory extension). That way you can have the context in request scope.
I was using a ServiceLocator which i was DIing with Unity
public ServiceLocator(IUserStore userStore, IProdcutsStore productsStore, ...etc) {}
public IUserStore UserStore
{
get { return userStore; }
}
This all worked fine, but I wanted lazy instantiation of the repositories as they have quite sparse use.
So my ServiceLocator now looks like
public ServiceLocator(IUnityContainer container) {}
public IUserStore UserStore
{
get { return (IUserStore)container.Resolve(typeof(IUserStore)); }
}
// ...etc
I'm now getting a really unhelpful ResolutionFailedException error
Resolution of the dependency failed,
type =
"DomainModel.DataServices.Interface.IUserStore",
name = "". Exception message is: The
current build operation (build key
Build
Key[DomainModel.DataServices.Interface.IUserStore,
null]) failed: The current type,
DomainModel.DataServices.Interface.IUserStore,
is an interface and cannot be
constructed. Are you missing a type
mapping? (Strategy type
BuildPlanStrategy, index 3)
Telling me my interface type cannot be instantiated because it is an interface is pretty pointless. I know it's an interface, that's why the container is supposed to be resolving it for me!
Anyway, the point to note here is that I know the type mapping in the config is fine, as when I was injecting the type interface directly instead of trying to lazy load, it resolved it with no problems.
What am I missing that means something somewhere has to change in order to lazy load this way?
Update: I am guessing what's happening here, is that when I DI the container into the ServiceLocator, the "main" container is instantiating a new container each time which is then not configured properly. I think maybe I need some way to specify that I was to pass this in as the container, rather than resolve it with a new instantiation.
You're going in a somewhat wrong direction... At first you've had a testable class that declared its dependencies in the constructor and you turned it into non-so-testable, asking for "something" inside a container... No good =(
You should either implement some factory interface for your expensive object and require it in the constructor, or (if you can) switch to Unity 2.0 and use the Automatic Factories:
public ServiceLocator(Func<IUserStore> userStoreBuilder)
//...
public IUserStore UserStore
{
get { return userStoreBuilder(); }
}
If you want to only create the instance of that object once, you can add cahcing to that property, or with .NET 4.0 you can try asking Lazy in the constructor.
P.S. Oh, yes. And answering your particualr question =) If you still want to inject an instance of your container somewhere else, you need to first register it inside itself =)
container.RegisterInstance<IUnityContainer>(container);
Fix (see comments) DO NOT register a Unity container inside itself, this will cause StackOverflowException in container.Dispose(), the correct instance will be injected as a dependency without the registration.
I have a class that implements an interface, which is made available for plugins.
The declaration of class is quite simple. There is only one instance of this class for an entire application. When the function that returns the interface is called, it calls _AddRef on the retrieved interface before passing it back as result. Unfortunately it works until I try to free the object (see "finalization" section) - it reports Invalid Pointer Operation. If I comment it out, it works fine (however FastMM reports memory leaks, so the object is not being freed).
Here is the part of the code in the function that returns the interface (in fact it is an overridden QueryInterface of my "ServicesManager" class).
if ConfigManager.GetInterface(IID, obj) then
begin
ISDK_ConfigManager(obj)._AddRef;
result:= 0;
end
and the code of ConfigManager class ...
type
TConfigManager = class(TInterfacedObject, ISDK_ConfigManager)
private
...
end;
var
ConfigManager: TConfigManager;
implementation
...
initialization
ConfigManager:= TConfigManager.Create();
finalization
if ConfigManager <> nil then
FreeAndNil(ConfigManager); //if I comment it out, it leaks the memory but no Invalid Ptr. Op. raises
What am I doing wrong?
I need to pass a reference to exactly this instance of ConfigManager.
The number one piece of advice you'll hear when dealing with interfaces is to never mix interface references with object references. What this means is that once you start referring to an object via an interface reference, you cease to refer to it via an object reference. Ever.
The reason is that the first time you assign an interface variable, the reference count of the object will become 1. When that variable goes out of scope or gets assigned a new value, the reference count becomes zero, and the object frees itself. This is all without any modification of the original object-reference variable, so when you later try to use that variable, it's not a null pointer, but the object it referred to is gone — it's a dangling reference. When you try to free something that doesn't exist, you get an invalid-pointer-operation exception.
Declare your ConfigManager variable as an interface. Don't free it yourself. Once you do that, you can move the entire declaration of TConfigManager into the implementation section because no code outside that unit will ever refer to it.
Also, there's rarely any reason to provide your own implementation of QueryInterface. (You said you overrode it, but that's impossible since it's not virtual.) The one provided by TInterfacedObject should be sufficient. The one you're providing is actually causing a memory leak because you're incrementing the reference count when you shouldn't be. GetInterface already calls _AddRef (by performing an interface assignment), so you're returning objects with inflated reference counts.
You said this is a plugin system? Are you loading your plugins as BPLs? I ran into that problem last week, actually. You can't rely on finalization to clear your interface references. You need to make sure to clear them before you unload the plugin, or its memory space becomes invalid.
Edit: By "clearing interface references" I mean calling _Release on them, either by manually setting it to nil or by letting the references go out of scope. If your interface manager holds interface references to the plugins, they'll get cleared when the interface manager gets destroyed.
I totally agree with Rob.
What most likely helps is rewriting your initialization code like below.
Now ConfigManager is of type ISDK_ConfigManager, and by assigning nil to it, the reference count will decrement.
When the reference count becomes zero, it will automatically become freed.
type
TConfigManager = class(TInterfacedObject, ISDK_ConfigManager)
private
...
end;
var
ConfigManager: ISDK_ConfigManager;
implementation
...
initialization
ConfigManager:= TConfigManager.Create();
finalization
ConfigManager := nil;
end;
--jeroen
does TConfigManager class has any method declared as "published"?