I have a custom module MyModule with a custom plugin MyPlugin in this plugin I want to send and receive data via a BinaryConnection.
Here is a simplified version of my code
[ServerModule(ModuleName)]
public class ModuleController : ServerModuleBase<ModuleConfig>
{
protected override void OnInitialize()
{
Container.LoadComponents<IMyPlugin>();
}
protected override void OnStart()
{
Container.Resolve<IBinaryConnectionFactory>();
Container.Resolve<IMyPlugin>().Start();
}
}
[Plugin(LifeCycle.Singleton, typeof(IMyPlugin), Name = PluginName)]
public class MyPlugin: IMyPlugin
{
private IBinaryConnection _connection;
public IBinaryConnectionFactory ConnectionFactory { get; set; }
public IBinaryConnectionConfig Config { get; set; }
public void Start()
{
_connection = ConnectionFactory.Create(Config, new MyMessageValidator());
_connection.Received += OnReceivedDoSomething;
_connection.Start();
}
}
When I start the Runtime I get a NullReferenceException because the ConnectionFactory is not injected. Where is my mistake here?
To use the binary connection in your module you can either instantiate TcpClientConnection and TcpListenerConnection manually or use your modules DI-Container, as you already tried and I would recommend.
To use it in your module, you need to register/load the classes into your container. Take a look at how the Resource Management registers them. In your OnInitialize you need:
Container.Register<IBinaryConnectionFactory>(); // Register as factory
Container.LoadComponents<IBinaryConnection>(); // Register implementations
Then you can add either a BinaryConnectionConfig entry to your config and decorate with [PluginConfigs(typeof(IBinaryConnection), false)] to select Socket as well as Client/Server from the MaintenanceWeb or use the derived type TcpClientConfig/TcpListenerConfig directly.
public class ModuleConfig : ConfigBase
{
[DataMember, PluginConfigs(typeof(IBinaryConnection), false)]
public BinaryConnectionConfig ConnectionConfig { get; set; }
}
In you plugin you can then inject IBinaryConnectionFactory and ModuleConfig to create the connection.
public class MyPlugin: IMyPlugin
{
private IBinaryConnection _connection;
public IBinaryConnectionFactory ConnectionFactory { get; set; }
public ModuleConfig Config { get; set; }
public void Start()
{
_connection = ConnectionFactory.Create(Config.ConnectionConfig, new MyMessageValidator());
_connection.Received += OnReceivedDoSomething;
_connection.Start();
}
}
PS: Resolving the factory in OnStart returns an instance, which you don't use and is unnecessary. Don't confuse Resolve(Find registered implementation and create instance) with Register.
Related
I'm converting an application to use Ninject as IoC and one of the things I need to convert is the existing Log4net implementation. The problem that I'm facing is that in the logfile (I use the XmlLayoutSchemaLog4j pattern) the class and method name seems to be of the calling parent instead of the actual caller.
I checked the types that are given to the new Log4NetLogger() and they seem to be of the exact same type as you specify using the LogManager.GetLogger(Methodbase.GetCurrentMethod.DeclaringType);
I made a small program that uses the old and the new implementation to check the differences but I can't seem to find them.
the outcome of the program is this:
Every level is a specific log entry in the code and the first entry of that level is done via Ninject and the second is via de LogManager.
As you can see the logger is the same, but the class and method differs.
the code from the project is:
internal class Program
{
private static IDoSomething _something;
static void Main()
{
log4net.Config.XmlConfigurator.Configure();
Init();
_something.StartSomething();
}
private static void Init()
{
var kernel = new StandardKernel(new NinjectSettings { LoadExtensions = false });
kernel.Load(Assembly.GetExecutingAssembly());
_something = kernel.Get<IDoSomething>();
}
}
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<ILogger>().ToMethod(x => new Log4NetLogger(x.Request.Target.Member.DeclaringType)).InTransientScope();
Bind<IDoSomething>().To<DoSomething>();
Bind<IDoSomethingElse>().To<DoSomethingElse>();
}
}
the dosomething:
public interface IDoSomething
{
void StartSomething();
}
public class DoSomething : IDoSomething
{
[Inject]
public ILogger Logger { get; set; }
public static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
[Inject]
public IDoSomethingElse DoSomethingElse { get; set; }
public void StartSomething()
{
Logger.Debug("Start StartSomething");
Log.Debug("Start StartSomething");
DoSomethingElse.StartSomethingElse();
Logger.Fatal("End StartSomething");
Log.Fatal("End StartSomething");
}
}
And the DoSomethingElse
public interface IDoSomethingElse
{
void StartSomethingElse();
}
public class DoSomethingElse : IDoSomethingElse
{
[Inject]
public ILogger Logger { get; set; }
public static ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
public void StartSomethingElse()
{
Logger.Info("Start Do Something Else");
Log.Info("Start Do Something Else");
StartSomethingLocal();
Logger.Error("End Do Something Else");
Log.Error("End Do Something Else");
}
private void StartSomethingLocal()
{
Logger.Warn("Start Do Something Local");
Log.Warn("Start Do Something Local");
Logger.Warn("End Do Something Local");
Log.Warn("End Do Something Local");
}
}
I tried several solutions for the type resolving in the new Log4NetLogger in the Load method but no luck.
I need help from you guys. Currently I am working on Dependency Injection in my Console Application. In single class i have define three layers just to understand dependency injection.
Actually I am trying to inject object of data acess layer which can be either Oracle or Sql based on the requirement.But injection is happening based on which layer is registerd last.Could any guys tell me how can I do proper injection?
UI LAYER:
class Program
{
static void Main(string[] args)
{
IUnityContainer objconatiner = new UnityContainer();
objconatiner.RegisterType<Customer>();
objconatiner.RegisterType<IDal, SqlserverDal>();
objconatiner.RegisterType<IDal, OracleServerDal>();
Customer ocust = objconatiner.Resolve<Customer>();
ocust.CustName = "Taylor Swift";
ocust.Add();
}
}
MIDDLE LAYER:
public class Customer
{
private IDal oidal;
public string CustName { get; set; }
public Customer(IDal idal)
{
oidal = idal;
}
public void Add()
{
oidal.Add();
}
}
DAL LAYER:
public interface IDal
{
void Add();
}
public class SqlserverDal : IDal
{
public void Add()
{
Console.Write("Now using Sql server");
}
}
public class OracleServerDal : IDal
{
public void Add()
{
Console.Write("Now using Orcale server");
}
}
This exact situation is where named registrations come in to play.
static void Main(string[] args)
{
IUnityContainer objconatiner = new UnityContainer();
objconatiner.RegisterType<Customer>();
objconatiner.RegisterType<IDal, SqlserverDal>("SqlServer");
objconatiner.RegisterType<IDal, OracleServerDal>("Oracle");
Customer ocust = objconatiner.Resolve<Customer>();
ocust.CustName = "Taylor Swift";
ocust.Add();
}
public class Customer
{
private IDal oidal;
public string CustName { get; set; }
public Customer([Dependency("SqlServer")]IDal idal)
{
oidal = idal;
}
public void Add()
{
oidal.Add();
}
}
Now both registrations can be used but you must specify which registration you want via name when you do your resolving, this can be done via attributes as I have shown above or via the Resolve call that takes in a string.
I'm looking for a way to keep track of the total time spent on the database, and merge it over one Service Operation call or maybe even an entire session. Since I'm currently using the default PerCall InstanceContextMode, the constructor of the Service class is called every time a service method is called, so I was thinking something like hooking into some pipeline method that is called before and after each service method, calling a non-empty constructor. And then injecting an object to pass further into the hierarchy:
[ServiceContract]
public interface IJobsService { ... }
public partial class JobsService : IJobsService
{
public PerformanceContext PerformanceContext { get; private set; }
JobsService() { ... }
JobsService(PerformanceContext context) : this()
{
RequestContext = context;
}
}
public class PerformanceContext
{
private object syncObj = new object();
private long? userID;
public long? UserID { ... }
public string Source { get; set; }
private long totalTicksUsed = 0;
public long TotalTicksUsed
{
get { return totalTicksUsed; }
private set { totalTicksUsed = value; }
}
public void AddTicksUsed(long ticks, long? userID)
{
Interlocked.Add(ref totalTicksUsed, ticks);
UserID = userID;
}
}
Then I would have the reference of it outside the scope of the service contract, and be able to log it there.
As it is now, the "simplest" way for me to implement this behavior is to call a logging function in the very end of every single service method, but I don't find it very pretty, if there's a better way.
I've tried following Explicitly calling a service constructor when hosting a WCF web service on IIS, Hooking into wcf pipeline and some of the Carlos Figueira MSDN blog: WCF Extensibility, without much success. I'm also having trouble finding much documentation on it general. In other words, I'm stuck.
I am a bit torn between the IOperationInvoker and the IInstanceProvider.
The IOperationInvoker has turned out to be fairly complicated for what I need, since I need to extend both synchronous and asynchronous calls. But it's advantage is that it is specifically made to perform actions before and after each method call. Although I'm still not entirely sure how to pass on an object to any service method, which I can use to track the use, lower in the hierarchy. And Carlos Figueira's blog on WCF Extensibility unfortunately doesn't touch on this in his example (he shows how to cache calls).
The IInstanceProvider turned out to be more simple for me to implement, and also makes it possible to perform actions before and after each operation - as long as the InstanceContextMode is PerCall. If I were to change it to PerSession, I would suddenly perform the actions once per session instead. But in my case, that's acceptable, since the primary objective is to merge the data as much as possible:
One of my Service classes with the custom ServiceBehavior Attribute and inheriting an abstract type that dictates we have a constructor that takes a PerformanceContext:
[ServiceContract]
public interface IJobsService { ... }
[PerformanceInstanceProviderBehavior]
public partial class JobsService : PerformanceMonitoredService, IJobsService
{
public PerformanceContext PerformanceContext { get; protected set; }
JobsService() { ... }
JobsService(PerformanceContext perfContext) : this()
{
PerformanceContext = perfContext;
}
...
}
IInstanceProvider which allows calling a specific constructor and injecting an IExtension into the pipeline, which we can obtain after the Service instance is released:
public class ServiceInstanceProvider : IInstanceProvider
{
public Type ServiceType { get; set; }
public ServiceInstanceProvider(Type serviceType) { ServiceType = serviceType; }
public object GetInstance(InstanceContext instanceContext)
{
return this.GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
var perfContext = new PerformanceInstanceContext();
instanceContext.Extensions.Add(new PerformanceInstanceExtension(perfContext));
return ServiceFactory.Create(ServiceType, perfContext);
//return new JobsService(perfContext);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
var perfContext = (instanceContext.Extensions.FirstOrDefault(ice =>
ice is PerformanceInstanceExtension)
as PerformanceInstanceExtension
)?.PerformanceContext;
//Handle the object which has been through the pipeline
//Note (IErrorHandler):
//This is called after "ProvideFault", but before "HandleError"
}
}
The IServiceBehavior and Attribute that will be added to all services that needs a PerformanceContext injected.
public class PerformanceInstanceProviderBehaviorAttribute : Attribute, IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
if (!ed.IsSystemEndpoint)
{
//Each Service Type is getting their own InstanceProvider,
//So we can pass the type along,
//and let a factory create the appropriate instances:
ed.DispatchRuntime.InstanceProvider =
new ServiceInstanceProvider(serviceDescription.ServiceType);
}
}
}
}
...
}
The IExtension that we can attach to the InstanceContext through the instance provider pipeline:
public class PerformanceInstanceExtension : IExtension<InstanceContext>
{
public PerformanceInstanceExtension()
{
PerformanceContext = new PerformanceContext();
}
public PerformanceInstanceExtension(PerformanceContext perfContext)
{
PerformanceContext = perfContext;
}
public PerformanceContext PerformanceContext { get; private set; }
public void Attach(InstanceContext owner) {}
public void Detach(InstanceContext owner) {}
}
The abstract service type that should allow this injection:
public abstract class PerformanceMonitoredService
{
public abstract PerformanceContext PerformanceContext { get; protected set; }
public PerformanceMonitoredService() {}
public PerformanceMonitoredService(PerformanceContext perfContext) {}
}
A factory for services that inherit PerformanceMonitoredService:
public class PerformanceServiceFactory
{
private static ConcurrentDictionary<Type, ConstructorInfo> Constructors
= new ConcurrentDictionary<Type, ConstructorInfo>();
public static object Create(Type type, PerformanceContext perfContext)
{
ConstructorInfo ctor;
if(Constructors.TryGetValue(type, out ctor))
{
return InvokeConstructor(ctor, perfContext);
}
else if (type.IsSubclassOf(typeof(PerformanceMonitoredService))
||type.IsAssignableFrom(typeof(PerformanceMonitoredService)))
{
ConstructorInfo newCtor = type.GetConstructor(
new[] { typeof(PerformanceContext) }
);
if(Constructors.TryAdd(type, newCtor))
{
return InvokeConstructor(newCtor, perfContext);
} else if(Constructors.TryGetValue(type, out ctor))
{
return InvokeConstructor(ctor, perfContext);
}
}
throw new ArgumentException(
$"Expected type inheritable of {typeof(PerformanceMonitoredService).Name}"}",
"type");
}
private static object InvokeConstructor(ConstructorInfo ctor,
PerformanceContext perfContext)
{
return ctor.Invoke(new object[] { perfContext });
}
}
I'm new to Unity and am trying to write some Unity logic which initialises and register/resolves a singleton instance of the Email object so that it can be used across several other objects, one example below being OperationEntity.
So when it's registered it populates the Email singleton with some values from a config file, then whenever an instance of OperationEntity is created (in my case it's being deserialized) it uses that same Email singleton. So all my client logic needs to do is deserialize OperationEntity and call PerformAction() - with the email instance taken care of by Unity.
public interface IEmail
{
string FromName { get; set; }
string FromEmailAddress { get; set; }
}
public class Email : IEmail
{
public string FromName { get; set; }
public string FromEmailAddress { get; set; }
public Email(string fromName, string fromEmailAddress)
{
FromName = fromName;
FromEmailAddress = fromEmailAddress;
}
}
public class OperationEntity
{
private readonly IEmail _email;
public int OperationId { get; set; }
public string OperationName { get; set; }
public string ToAddress { get; set; }
public OperationEntity(IEmail email)
{
_email = email;
}
public void PerformAction()
{
_email.ToAddress = ToAddress;
_email.Body = "Some email body";
_email.Deliver();
}
}
Any help would be appreciated in getting this Unity code to work
public static void Register(IUnityContainer container)
{
container
.RegisterType<IEmail, Email>(
new InjectionFactory(c => new Email(
"To Name",
"to#email.com")));
var email = container.Resolve<IEmail>();
container.RegisterType<OperationEntity>(
"email", new ContainerControlledLifetimeManager(),
new InjectionConstructor(email));
}
First, you need a proper lifetime manager the ContainerControlledLifetimeManager is for singletons.
For custom initialization, you could probably use InjectionFactory
This lets you write any code which initializes the entity.
Edit1: this should help
public static void Register(IUnityContainer container)
{
container
.RegisterType<IEmail, Email>(
new ContainerControlledLifetimeManager(),
new InjectionFactory(c => new Email(
"To Name",
"to#email.com")));
}
and then
var opEntity = container.Resolve<OperationEntity>();
Edit2: To support serialization, you'd have to rebuild dependencies after you deserialize:
public class OperationEntity
{
// make it public and mark as dependency
[Dependency]
public IEmail _email { get; set;}
}
and then
OperationEntity entity = somehowdeserializeit;
// let unity rebuild your dependencies
container.BuildUp( entity );
You could use:
container.RegisterType<IEmail, Email>(new ContainerControlledLifetimeManager());
If IEmail is a singleton with no dependencies (just custom arguments), you can new it up yourself:
container.RegisterInstance<IEmail>(new Email("To Name", "to#email.com"));
That will register the supplied instance as a singleton for the container.
Then you just resolve the service:
container.Resolve<OperationEntity>();
And because you are resolving a concrete type, there is no registration required. Nevertheless, if you would like that service to also be a singleton, you can register it using ContainerControlledLifetimeManager and then all calls to resolve (or when injecting it as a dependency to another class) will return the same instance:
container.RegisterType<OperationEntity>(new ContainerControlledLifetimeManager());
You can, for example, use this code:
public class example : MonoBehaviour
{
public static example instance;
public void Start()
{
(!instance)
instance = this;
}
}
You could implement your own singleton class and extend any class form it.
public class MyClass : MonoBehaviour {
private static MyClass _instance;
public static MyClass Instance { get { return _instance; } }
private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
} else {
_instance = this;
}
}
}
So we have a class that does needs to output the result of an operation. Now this was tightly-coupled to emails, however with dependency injection I thought I could add more persistence options, eg. save to disk.
The problem is that saving to disk requires a path, while 'saving' as an email requires other details (from, to, etc).
Is this something that can be achieved through dependency injection? Or am I doing the whole thing wrong? Check code below and my comments to better understand my problem...
public class OriginalClass
{
IPersistence _persistence;
public OriginalClass(IPersistence persistence)
{
this._persistence = persistence;
}
public void DoSomething()
{
// I have all the information needed to send an email / save to disk. But how do I supply it?
this._persistence.Put("Message to save");
}
}
public interface IPersistence
{
bool Put<T>(T data);
}
public class EmailPersistence : IPersistence
{
public bool Put<T>(T data)
{
// How am I going to get the FROM and TO details?
return EmailManager.Send("FROM", "TO", data.ToString());
};
}
public class DiskPersistence : IPersistence
{
public bool Put<T>(T data)
{
// How am I going to get the SAVE PATH details?
// I just used a new initialization. So I'm probably doing this wrong as well...
new System.IO.StreamWriter("SAVE PATH").Write(data.ToString());
return true;
}
}
What you need to do is pass 'just enough' contextual information about the message to the persistence class. Passing on email-specific information like from and to however, causes you to leak implementation details of the persistence mechanism into OriginalClass, which is not something you should want. Doing this will cause you to have to change the OriginalClass everytime you add a new IPersistence implementation. This is obviously bad (it breaks both OCP and DIP).
So what exactly to supply is something only you can determine, but it could be something identifier that allows an implementation to retrieve the required information to operate. This could be something like the ID of the Contactperson or organization for who the message is written. This way you only have to pass in the message and this ID and the implementation can use this ID to query the database to get whatever it needs.
However, if these values do not change during the application's runtime, the solution is completely different. In that case you should simply use constructor injection:
public class EmailPersistence : IPersistence {
private readonly MailAddress from;
private readonly MailAddress to;
public EmailPersistence(MailAddress from, MailAddress to) {
this.from = from;
this.to = to;
}
public bool Put(string data) {
// How am I going to get the FROM and TO details?
return EmailManager.Send(this.from, this.to, data.ToString());
};
}
Since the settings do not change, you can load them from the config file (or from anywhere) during application startup and can simply create a new EmailPersistence using these fixed configuration values.
Something like this should work, As now IEmailManager can also go via the DI framework, all you need to do is to bootstrap the EmailManager Construction.
public class OriginalClass
{
IPersistence _persistence;
public OriginalClass(IPersistence persistence)
{
this._persistence = persistence;
}
public void DoSomething()
{
// I have all the information needed to send an email / save to disk. But how do I supply it?
this._persistence.Put("Message to save");
}
}
public interface IPersistence
{
bool Put<T>(T data);
}
public class EmailPersistence : IPersistence
{
private readonly IEmailManager _manager;
public EmailPersistence(IEmailManager manager)
{
_manager = manager;
}
public bool Put<T>(T data)
{
// How am I going to get the FROM and TO details?
return _manager.Send();
}
}
public class EmailManager : IEmailManager
{
public string From { get; set; }
public string To { get; set; }
public bool Send()
{
throw new NotImplementedException();
}
public dynamic Data { get; set; }
}
public interface IEmailManager
{
string From { get; set; }
string To { get; set; }
dynamic Data { get; set; }
bool Send();
}
public class DiskPersistence : IPersistence
{
public string Path { get; set; }
public DiskPersistence(string path)
{
Path = path;
}
public bool Put<T>(T data)
{
// How am I going to get the SAVE PATH details?
// I just used a new initialization. So I'm probably doing this wrong as well...
new System.IO.StreamWriter(Path).Write(data.ToString());
return true;
}
}