Reputation:
I run in to this situation a lot. I'm finally seeking an answer on how I can do this. I understand that there are many ways, but most are dirty and include bad practices.
Just to make it clear, this is not asking for your opinion, it's asking how the majority of programmers deal with this kind of problem, pretty much any way possible that doesn't include really bad code.
I have a class called CoreContext
, which I property inject new instances into the property's class names as show below. But what happens when I need the parent class that has initiated that class?
Say I need an instance of the CoreContext
inside SocketHandler
(ClientSocketHandler
). How would I go about doing that? I feel like there's a really simple way, but I've never understood what that is.
Is there an even simple call stack I'm not seeing, or what? Note that I would prefer to do this, the way I am doing, Object initialization, and not assigning the properties later.
var coreContext = new CoreContext
{
ConfigHandler = new JsonConfigHandler(),
SocketHandler = new ClientSocketHandler(coreContext, IPAddress.Parse(""), 30),
PacketProvider = new PacketProvider
{
Events = new Dictionary<short, Action<ICoreContext, IIncomingPacket>>
{
{ IncomingPacketIds.AuthError, AuthErrorEvent.Process },
{ IncomingPacketIds.DeviceInformation, DeviceInformationEvent.Process },
{ IncomingPacketIds.AuthComplete, AuthCompleteEvent.Process },
}
}
};
Upvotes: 2
Views: 66
Reputation: 109732
If you use constructor injection to pass a factory delegate to create the ClientSocketHandler
you can circumvent this problem, but I'm not entirely sure that this is an improvement on simply setting the property after creation.
(Well, it is an improvement in that constructor injection is (IMO) better than propery injection.)
Anyway, here's an example in case it's of use to you.
Note the use of context => new ClientSocketHandler(context)
to pass a factory delegate to the CoreContext
constructor.
Then inside the CoreContext
constructor you can pass this
to the delegate.
using System;
namespace Demo
{
class Program
{
public static void Main(string[] args)
{
var coreContext = new CoreContext(context => new ClientSocketHandler(context))
{
ConfigHandler = new ConfigHandler()
};
}
class ConfigHandler {}
class ClientSocketHandler
{
readonly CoreContext _coreContext;
public ClientSocketHandler(CoreContext coreContext)
{
_coreContext = coreContext;
}
}
class CoreContext
{
public CoreContext(Func<CoreContext, ClientSocketHandler> socketHandlerFactory)
{
SocketHandler = socketHandlerFactory(this);
}
public ClientSocketHandler SocketHandler { get; private set; }
public ConfigHandler ConfigHandler { get; set; }
}
}
}
Note that if you use constructor injection, you can omit the setter for SocketHandler
. Also note that you should be injecting via interfaces, but I've omitted that for brevity. I'm assuming that you don't want to new
up an instance of ClientSocketHandler
right there in the constructor!
Upvotes: 2