I have a class
public class Broker
{
public Broker(string[] hosts, string endPoint, string port, Type remoteType)
{
}
}
Which I want to configure using Unity XML Configuration, I can configure it using code in C# as follows already, where "container" is my Unity container
container.Configure<InjectedMembers>()
.ConfigureInjectionFor<Broker>("myBroker",
new InjectionConstructor(hosts, endPoint, port, new InjectionParameter(typeof(IMyBrokeredObject))));
and it will happly resolve using the normal unity calls
container.Resolve("myBroker");
But currently my xml cannot resolve the final parameter IMyBrokeredObject, I get a resolution exception, as Unity is trying to resolve the type insted of simply injecting the type, as it does in the code above.
Any Ideas?
Have you defined the type in the configuration file:
<unity>
<typeAliases>
<typeAlias alias="IMyBrokeredObject" type="MyAssembly.IMyBrokeredObject, MyAssembly" />
</typeAliases>
<containers>
<container>
<types>
<!-- Views -->
<type type="IMyBrokeredObject" mapTo="MyAssembly.MyBrokeredObjectImplementation, MyAssembly" />
But my problem is that there is no implementation available for the IMyBrokeredObject, what is actually happening in the background of this is that the broker provides remote objects given an interface, the actual implementation is somewhere else.
In code I can get the container to provide an broker by giving an "InjectionParameter", I cannot find out how to do this in the xml configuration.
its tricky because I dont want the container to give an instance of the interface but to actually pass the interface as is, the "InjectionParameter" is a store for a value, the stored value is handed in when the object is created by the container, as is. What I am looking for is the required configuration xml to create the InjectionParameter and give it the value, if that is at all possible?
Related
I developed a small application that stores data coming from a device: I chose to store data in JSON format, and the serialization/deserialization of the data works just fine, even if it involves some custom types created by me...but only I work in the IDE (Eclipse, for that matter).
When I export a runnable JAR file though, the deserialization of the data encounters some kind of problem, because the software always throws this exception:
Caused by: java.lang.UnsupportedOperationException: Cannot allocate class LocalDateTime
at com.google.gson.internal.UnsafeAllocator$4.newInstance(UnsafeAllocator.java:104)
at com.google.gson.internal.ConstructorConstructor$14.construct(ConstructorConstructor.java:225)
... 88 common frames omitted
I thought I'd encounter problems with custom types, not a built-in one. At this point, I discovered two things:
if I use a full JRE 9 to run the JAR file, the exception is not thrown: I double checked the modules included in the custom JRE I created with Jlink.exe, and everything is included correctly. I still want to use a smaller JRE, so I did not investigate further yet (I guess this explains why in the IDE it works perfectly)
I added a custom deserializer to the Gson object (see below), with which I simply manually converted the JSON string into a valid data, and that avoided the exception on the LocalDateTime class...but the exception reappeared simply on another class, this time a custom-made one.
At this point, I guess I can simply add a deserializer for each data type that causes problem, but I'm wondering why the issue won't happen with a full JRE, and why a smaller JRE causes this, even if all the modules required are included. Maybe it's worth mentioning also that I added no custom serializer to the Gson object that saves the data, it is all serialized as per Gson default.
LocalDateTime deserializer:
#Override
public LocalDateTime deserialize(JsonElement json, java.lang.reflect.Type type,
JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
JsonObject joDate = json.getAsJsonObject().get("date").getAsJsonObject();
JsonObject joTime = json.getAsJsonObject().get("time").getAsJsonObject();
//JSON example: {"date":{"year":2019,"month":1,"day":9},"time":{"hour":6,"minute":14,"second":1,"nano":0}
return LocalDateTime.of(joDate.get("year").getAsInt(),
joDate.get("month").getAsInt(),
joDate.get("day").getAsInt(),
joTime.get("hour").getAsInt(),
joTime.get("minute").getAsInt(),
joTime.get("second").getAsInt(),
joTime.get("nano").getAsInt());
}
}
Jdeps.deps modules list:
com.google.gson
java.base
javafx.base
javafx.controls
javafx.fxml
javafx.graphics
org.slf4j
After the answer I received, I opened an issue here.
TL;DR
You need a runtime image (e.g. full JDK or something built with jlink) that includes the module jdk.unsupported.
Full Answer
GSON wants to create instances of classes it deserializes without calling any constructors (so nothing gets initialized without GSON saying so). This can't normally be done, but sun.misc.Unsafe offers a way to do this with the method allocateInstance. To that end, GSON needs an instance of sun.misc.Unsafe. The topmost frame in the call stack is from UnsafeAllocator, which uses common trickery to get Unsafe.
The problem is, sun.misc.Unsafe is in module jdk.unsupported, which is present in a full JDK but you won't usually find in runtime images.
When creating your runtime image with jlink, make sure to include the option --add-modules jdk.unsupported and you should be good to go.
Arguably, GSON should declare an optional dependency on jdk.unsupported with requires static.
I have faced the same issue when packing compose a desktop application.
update build.gradle file, add an unsupported module.
compose.desktop {
application {
mainClass = "MainKt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "admin"
packageVersion = "1.0.0"
modules("java.sql")
modules("jdk.unsupported")
}
}
}
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.
I've been running into endless problems attempting to use Windsor with Web API and injecting HttpRequestMessage into downstream dependencies of a controller. Since I've tried all the matching answers on Stackoverflow, I'd like to ask the question in a different way:
In Castle Windsor, how can I resolve a component instance while supplying a value for a downstream dependency? That is, the supplied value is required by a component that is required by the component being resolved.
For context, I'm trying to inject HttpRequestMessage so that I can use it to resolve the request context (primarily to resolve an absolute URL).
Edit I'd also like to point out that I don't currently have a dependency on Web Host / System.Web and I'd rather not change that.
A proper approach is to
Create IMyDesiredRouteParameterProvider
Implement it. Get the current request inside it and get the url
Register it and inject it in the desired dependent class via constructor.
I made myself such an implementation and I can say that this way it works fine. You can make Web.Infrastructure assembly and put the implementation there. Or put both the interface and the implementation there if you are going to reference it from another web module.
using System;
using System.Web;
namespace RouteParameterProvider
{
interface IMyRouteParameterProvider
{
string GetRouteParameter();
}
public class ControllerActionMethodRouteParameterProvider : IMyRouteParameterProvider
{
public string GetRouteParameter()
{
string Parameter = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"] as string;
if (string.IsNullOrEmpty(Parameter))
{
throw new InvalidOperationException();
}
return Parameter;
}
}
}
You can get every possible thing that the Request Context contains from :
HttpContext.Current.Request.RequestContext
And it will be better if you rethink your design decision :
I need HttpRequestMessage to be regstered prior to creating each
instance of SomethingController so that it will be available down at
the LinkGenerator layer.
Containers are to be initialized at runtime and then used to resolve.
I need HttpRequestMessage to be regstered prior to creating each
instance of SomethingController so that it will be available down at
the LinkGenerator layer.
It sounds like you want to register an item with the container at runtime, post-startup. In general, this is not a good practice--registration should be a discrete event that happens when the app is fired up, and the container's state should not be changed during runtime.
Dependency Injection is about resolving service components, not runtime state--state is generally passed via methods (method injection). In this case it sounds like your LinkGenerator component needs access to the ambient state of the request.
I'm not that familiar with HttpRequestMessage, but this answer seems to show that it is possible to retreive it from HttpContext.Current. You could make this a method on your LinkGenerator class, or wrap this call in a separate component that gets injected into LinkGenerator (HttpRequestMessageProvider?). The latter would be my preferred method, as it allows LinkGenerator to be more testable.
Given the lack of a clean way of doing this and Web API not providing information as to the hosted endpoint beyond per-request context objects, I ended up injecting the base url from configuration.
Is this library by Mark Seemann the answer? In the description he writes explicitly :
This approach enables the use of Dependency Injection (DI) because the
request can be injected into the services which require it.
Then gives an example :
// Inside an ApiController
var uri = this.Url.GetLink(a=> a.GetById(1337));
By which you can then pass the URL down the road in the service that you have injected in the controller.
UPDATE :
Mark Seemann wrote about the same exact problem here:
"Because HttpRequestMessage provides the context you may need to
compose dependency graphs, the best extensibility point is the
extensibility point which provides an HttpRequestMessage every time a
graph should be composed. This extensibility point is the
IHttpControllerActivator interface:..."
This way you can pass request context information to a component deep in the object graph by getting from the HttpRequestMessage and passing it to the DI container.
Just take a look at the interface of IHttpControllerActivator.
The WEB API framework gets the IHttpControllerActivator through DependencyResolver. You probably already replaced it by your CastleWindsorDependencyResolver. Now you have to implement and register your HttpControllerActivator and register it.
When the WEB API framework gets IHttpControllerActivator from DependencyResolver (your Castle Windsor DR) and calls IHttpControllerActivator.Create() it will pass you the HttpRequestMessage. You can get your info from there and pass it to the your CastleDR before you call Resolve(typeof(MyController)) which will resolve the whole object graph - that means you will have MyHttpContextInfo to inject in your XYZComponent deep in the resolution stack.
This way tou are passing the arguments in the last possible moment but it is still possible. In Castle Windsor I make such passing of arguments though CreationContext.AdditionalArguments["myArgument"];.
I am having issues with serializing objects to JSON, and being new to WCF, I am having issues on where to start in terms of debugging. All I get if I hit the service by typing the url in the browser is page not available.
The scenario: I have class A which inherits a List of class B. If I comment out in Class A where it adds to it's collection, I can at least hit the service (just obviously no data will be present), but if it adds to its collection, I can no longer hit the service.
Interface:
<OperationContract()> _
<WebGet(UriTemplate:="getAdverseReactions", responseFormat:=WebMessageFormat.Json)> _
<ServiceKnownType(GetType(AdverseReactions))> _
<ServiceKnownType(GetType(AdverseReaction))> _
Function GetAdverseReactions() As AdverseReactions
Implementing interface:
Public Function GetAdverseReactions() As AdverseReactions Implements IPortalCoreService.GetAdverseReactions
Return CoreServiceController.GetAdverseReactions()//which returns class A
End Function
Class A:
<CollectionDataContract(Name:="AdverseReactionsCollection", ItemName:="AdverseReaction")> _
Public Class AdverseReactions
Inherits List(Of AdverseReaction)
Class B:
<DataContract(IsReference:=True)> _
Public Class AdverseReaction
I stepped through the code via attaching a process, and no exceptions are thrown and I can confirm that the objects are returned as they should be, I just obviously cannot serialize it. I have read about circular references, and a friend of mine suggested that these two classes might be serializing each other in an infinite manner.
My main question: Is there a place I can look to see why this is occurring, or at least some more information about it? This issue has been handling me, all I want is to serialize this and when I do I think I will take a weeks vacation :).
Add the following block to your web.config <configuration> block
<system.diagnostics>
<sources>
<source name="System.ServiceModel"
switchValue="Information, ActivityTracing"
propagateActivity="true">
<listeners>
<add name="traceListener"
type="System.Diagnostics.XmlWriterTraceListener"
initializeData="c:\log\WebTrace.svclog" />
</listeners>
</source>
</sources>
</system.diagnostics>
and ensure the directory specified (c:\log) exists and is writable by the IIS service.
Once this is done, perform the action that causes the serialization issue then navigate to the directory and double-click the generated svclog file.
This will open the file in the Microsoft Service Trace Viewer. Once this is opened, you will see errors displayed in red down the left-hand side.
Clicking on one of these will show the details in the top right pane and you can click on each of the actions to determine what WCF is complaining about.
While this is slightly dated (2010), I think it will give you some ideas of paths to try.
Quickly finding WCF Serialization/Deserialization Issues
This previous StackOverflow question might help to:
How to trace WCF serialization issues / exceptions
I have an configuration error with Unity.
I am trying to implement http://unitymvc3.codeplex.com/, but i am stucked right now, because of this:
In my unity configuration I have this settings:
<register type="IMainDbContext" mapTo="WorkflowContext">
<lifetime type="hierarchical" />
<constructor></constructor>
</register>
But at the time of creating unity, (my simple code is here:)
UnityConfigurationSection section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
if (section != null)
{
section.Configure(container);
}
this.container = container;
everything is configured great, except of registration "IManDbContext" which has LifetimeManagerType = {Name = "TransientLifetimeManager" FullName = "Microsoft.Practices.Unity.TransientLifetimeManager"}, but it should be hierarchical lifetime manager
Have you got any ideas how tell unity (in configuration, not in code) i want hierarchical lifetime manager?
Thanks for any tips.
My error was caused by this error:
I have multiple DbContext, but they was badly configured:
<register type="IMainDbContext" mapTo="WorkflowContext">
<lifetime type="hierarchical" />
<constructor></constructor>
</register>
<register type="IReportDbContext" mapTo="SomeBadContext">
<lifetime type="hierarchical" />
<constructor></constructor>
</register>
When I was using this configuration, which was bad, unity simple don`t configure any lifetime manager. After I set these context right, unity used my lifetime manager configurations just right.
I don't think you can. If you're specifying the lifetime type you need to either supply "singleton" or "external" (external being a custom lifetime).
Link to Unity Schema Documentation
In fairness, unless you're using multiple Unity containers I don't see the value of having a hierarchical lifetime manager, as this is designed to ensure that you only have one instance of your type instantiated in the main unity container and any child containers you generate from it.
So, unless you're planning on generating child containers and want a separate instance of your IMainDbContext inplmenting object, you might as well just using "singleton" lifetime manager.