I'm using the Microsoft Unity 2.1 IoC container. This doesn't feature automatic / convention-based configuration like Windsor or StructureMap, so I've downloaded UnityConfiguration 1.4.1 (see http://thedersen.com/projects/unityconfiguration/) via NuGet.
Configuration is performed by creating UnityRegistries (like Installers and Modules in other containers). I've created a couple of these for registering different types of classes:
internal class WidgetRegistry : UnityRegistry
{
public WidgetRegistry()
{
Register<IWidget, Widget>();
}
}
internal class GubbinsRegistry : UnityRegistry
{
public GubbinsRegistry()
{
Register<IGubbins, FirstGubbins>().WithName("gubbins1");
Register<IGubbins, SecondGubbins>().WithName("gubbins2");
}
}
In the composition root, I can add the following:
container.Configure(
unityRegistry =>
{
unityRegistry.AddRegistry<WidgetRegistry>();
unityRegistry.AddRegistry<GubbinsRegistry>();
});
...and everything works properly. But this means manually modifying the composition root code every time I add a new registry. What I'd like to do is use the scanning facilities of UnityConfiguration to do this automatically for me; that is, remove the above calls to AddRegistry() and replace them with something like this:
container.Configure(
unityRegistry =>
{
unityRegistry.Scan(
scanner =>
{
scanner.AssembliesInBaseDirectory();
scanner.ForRegistries();
});
});
Unfortunately, this doesn't work at all. The WidgetRegistry and GubbinsRegistry constructors are never invoked.
I suspect I'm not using this feature of UnityConfiguration correctly. Does anyone have any ideas how to do this?
Many thanks,
Matt
Try changing your registries from internal to public.
Related
Straightforward question is: are Microsoft.Extensions.Options.IOptions meant to be used only within the context of umbrella app (web app in this case) or in class libraries also?
Example:
In a n-layered, asp.net core app we have services layer that is dependant on some settings coming from appsettings.json file.
What we first started with is something along these lines in Startup.cs:
services.Configure<Services.Options.XOptions>(options =>
{
options.OptionProperty1 = Configuration["OptionXSection:OptionXProperty"];
});
And then in service constructor:
ServiceConstructor(IOptions<XOptions> xOptions){}
But that assumes that in our Service layer we have dependecy on Microsoft.Extensions.Options.
We're not sure if this is recomended way or is there some better practice?
It just feels a bit awkward our services class library should be aware of DI container implementation.
You can register POCO settings for injection too, but you lose some functionalities related to when the appsettings.json gets edited.
services.AddTransient<XOptions>(
provider => provider.GetRequiredService<IOptionsSnapshot<XOptions>>().Value);
Now when you inject XOptions in constructor, you will get the class. But when your edit your appsettings.json, the value won't be updated until the next time it's resolved which for scoped services would be on next request and singleton services never.
On other side injecting IOptionsSnapshot<T> .Value will always get you the current settings, even when appsettings.json is reloaded (assuming you registered it with .AddJsonFile("appsettings.json", reloadOnSave: true)).
The obvious reason to keep the functionality w/o pulling Microsoft.Extensions.Options package into your service/domain layer will be create your own interface and implementation.
// in your shared service/domain assembly
public interface ISettingsSnapshot<T> where T : class
{
T Value { get; }
}
and implement it on the application side (outside of your services/domain assemblies), i.e. MyProject.Web (where ASP.NET Core and the composition root is)
public class OptionsSnapshotWrapper<T> : ISettingsSnapshot<T>
{
private readonly IOptionsSnapshot<T> snapshot;
public OptionsSnapshotWrapper(IOptionsSnapshot<T> snapshot)
{
this.snapshot = snapshot ?? throw new ArgumentNullException(nameof(snapshot));
}
public T Value => snapshot.Value;
}
and register it as
services.AddSingleton(typeof(ISettingsSnapshot<>), typeof(OptionsSnapshotWrapper<T>));
Now you have removed your dependency on IOptions<T> and IOptionsSnapshot<T> from your services but retain all up advantages of it like updating options when appsettings.json is edited. When you change DI, just replace OptionsSnapshotWrapper<T> with your new implementation.
I have a jodd project that uses Proxetta and JTX for creating transactions over services classes. The issue is that when I try to debug a service class I receive :
Unable to install breakpoint due to missing line number attributes
I suspect that there has something to do with they way Proxetta generates my proxies classes as it seems that in Spring if you have no interface for a class the same happens.
I use Eclispe and here how Proxetta is initialized:
public void initProxetta() {
ProxyAspect txServiceProxy = new ProxyAspect(AnnotationTxAdvice.class,
new MethodAnnotationPointcut(Transaction.class) {
#Override
public boolean apply(MethodInfo mi) {
return isPublic(mi) &&
isTopLevelMethod(mi) &&
matchClassName(mi, "*ServiceImpl") &&
super.apply(mi);
}
});
proxetta = ProxyProxetta.withAspects(txServiceProxy);
proxetta.setClassLoader(this.getClass().getClassLoader());
}
Would you please try the following quickstart webapp1 example?
Its gradle project, so you can quickly import it in any IDE. In this example, we create proxy almost exactly like you above, but on actions (which should not make a difference). Now try to put a breakpoint into the IndexAction - this one gets proxified, for example. I am able to put break point there in IntelliJ IDEA.
Moreover, I dunno why Eclipse complains about the breakpoint in the service implementation class, since Proxetta as you used above creates a proxy subclass, and does not change the target class in any way. So when you put breakpoint in the service implementation code, it is in your class, not proxy class.
Finally, did you put BP on the method, or inside the code? If it is the first (on the method), then please try to put the BP inside the code of your service: eg on first line of the method body.
I know we can implement IWantCustomInitialization to configure NServicebus with other IoC continers lets say Castle.Windsor for instance, but I found this is obsoleted. in new version alternatively I used INeedInitialization, but it also didn't solve my issue because the container was specified before "INeedInitialization.Customize" invocation, So
at last I implemented IConfigureThisEndpoint as my final solution.
To sum up my question; when to use "INeedInitialization" and "IConfigureThisEndpoint"?
Best Regards
Both give you access to do basically the same things. The big difference is that IConfigureThisEndpoint is once per endpoint, so you use that to configure truly endpoint-specific things. INeedInitialization can have many implementations, and all of them get executed. So you can package up multiple INeedInitialization behaviors in a Conventions assembly and use them throughout your solution to carry out tasks common to multiple (or all) endpoints.
This has been changed a bit over time and v5 of NServiceBus introduce a different API. For context you can read through the following bug comments. What the intent is:
IConfigureThisEndpoint - for configuring the Endpoint. Can only have 1 per instance.
INeedInitialization - for configuring a component used by the Endpoint. Can have multiple implementations of this per instance.
An example of when to use IConfigureThisEndpoint (see full example)
public class EndpointConfig : IConfigureThisEndpoint, AsA_Server, UsingTransport<MsmqTransport>
{
public void Customize(BusConfiguration configuration)
{
configuration.UsePersistence<NHibernatePersistence>();
}
}
An example of when to use INeedInitialization (see full example)
class ResponderInstaller : INeedInitialization
{
public void Init()
{
Configure.Instance.Configurer.ConfigureComponent<CustomHttpResponder>(DependencyLifecycle.InstancePerCall);
}
}
Could anyone give an example of implementation? Is it done with ViewModel implementing INotifyPropertyChanged (and raising events, as it's done in Silverlight) or some other way? How is ViewModel bound to the view?
All examples I've found so far are incomplete or outdated (refer to Silverlight apps, not Xaml ones).
In the case of Windows RT I would advise to look towards PRISM. It provides really good modern development practices. You will get suitable navigation service, app lifecycle management, great MVVM support and very flexible view and ViewModels resolution mechanism.
You can easily add it to your project via NuGet.
It has pretty good documentation, so if you have any questions you can find an answer on MSDN or even download free book Prism for the Windows Runtime. Our team has successful experience in building projects using PRISM.
I currently use the following approach in my own Universal/W8.1/WP8.1 apps. This approach uses the RArcher WinRT Toolkit, which is an experimental toolkit based on the MVVM pattern.
It provides a way to maintain app state and you can use the ViewModelBase to implement INPC.
It also uses the Unity dependency injection container.
I'd start with making the ViewModelLocator an application-wide resource, so my Views can access it easily.
<Application.Resources>
<vm:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>
The view can use it like so:
<Page.DataContext>
<Binding Source="{StaticResource ViewModelLocator}" Path="MainViewModel" />
</Page.DataContext>
The ViewModelLocator looks like this:
public sealed class ViewModelLocator
{
public ViewModelLocator()
{
RegisterIoCBindings();
}
public IMainViewModel MainViewModel
{
get { return IocContainer.Get<IMainViewModel>(); }
}
private void RegisterIoCBindings()
{
IocContainer.Container.RegisterType(typeof(IMainViewModel), typeof(MainViewModel),
null, new ContainerControlledLifetimeManager());
}
}
The MainViewModel has the ViewModelBase as baseclass and implements the IMainViewModel:
public sealed class MainViewModel : ViewModelBase, IMainViewModel
{
private string myText;
[AutoState]
public string MyText
{
get { return myText; }
set
{
myText = value;
OnPropertyChanged();
}
}
public MainViewModel() // You can use constructor injection here
{
}
}
That is the basic setup. And as the others have stated, MVVM is a pattern and there a many ways to use it. I would say, use what feels good ;-)
If you like to know more about this approach, check out the toolkit and unity DI.
There is no difference, it's the same. Because MVVM is a pattern. You can implement it to your windows phone app easily. I'm using MVVM Light for my wp apps and EventToCommand behavior to raise events. I have an app open sourced on GitHub, you can check it out if you want.
So SimpleInjector now has a packaging nuget that you can use to isolate different aspects of root composition.
Say I have a configurable composition root in a library that is reused by multiple projects in an application. For example, in an Azure solution I might have a Web role and a Worker role which share a large set of the same dependencies for the most part, but with slightly different configuration options depending on the consumer. When I compose the root, I can pass in a plain old RootCompositionSettings object with properties that tell SimpleInjector how to register dependencies.
However, I am not sure how (or if) I can pass these settings to an IPackage instance. Is it possible to pass custom settings to a SimpleInjector package, and if so, how?
I see that the standard practices for registering packages is to invoke either
container.RegisterPackages(); // scans all loaded assemblies for IPackage
// or
container.RegisterPackages(IEnumerable<Assembly>) // specific assemblies only
...so how can we pass parameters into the packaging instance(s)? Is there some way to do it via the container?
The trick here is to pass the information on with the container to the package. You can do this by using the container's Items dictionary, that is much like ASP.NET's HttpContext.Items collection. This can be done as follows:
using SimpleInjector.Advanced;
container.SetItem(typeof(RootCompositionSettings), settings);
container.RegisterPackages();
Now inside your packages, you can do the following:
var settings =
(RootCompositionSettings)container.GetItem(typeof(RootCompositionSettings));
Please note that:
SetItem and GetItem are extension methods that are located in the SimpleInjector.Advanced namespace. Those methods allow you to access the (internal) Items dictionary.
You can pass in any key you like. Passing in typeof(RootCompositionSettings) is just convenient in this case, but not required.
If you need to call the settings in more places, it might be useful to create a more specific extension method that allows you to access the setting instance, but that's up to you.
Another option is to not use the IPackage interface and the SimpleInjector.Packaging library at all. In most cases it doesn't really add anything and you could simply define a public static method in the assembly that does the same as a package does. For instance:
public static class BusinessLayerBootstrapper
{
public static void Bootstrap(Container container, ScopedLifestyle scopedLifestyle,
RootCompositionSettings settings)
{
// Here the same logic as what you would write in your package.
}
}
Most applications are not that dynamic that you need to load assemblies dynamically and the startup project usually has a hard reference to all the other assemblies. In that case it is perfectly sane to simply call a static method.
And even if you have the requirement of dynamically loading assemblies and allowing them to register their stuff in the container, it's quite trivial to build your own IPackage abstraction instead:\
// Your own IPackage interface
public interface IPackage
{
void RegisterServices(Container container, RootCompositionSettings settings);
}
// Your own extension method
public static void RegisterPackages(this Container container,
RootCompositionSettings settings)
{
var packages =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetExportedTypes()
where typeof(IPackage).IsAssignableFrom(type)
where !type.IsAbstract
select (IPackage)Activator.CreateInstance(type);
packages.ToList().ForEach(p => p.RegisterServices(container, settings));
}
In fact, except for some extra validations and filtering out dynamic assemblies, the SimpleInjector.Packaging project is not much more than this.