WCF Data Service and Castle Windsor - service

I am trying to use the Castle Windsor with WCF Data Service. I have created an Entity Data Model say "Person" and added a WCF Data Service called "MyService.svc". This is then exposed through OData...
public class MyService: DataService<Person>
...
Now, the question is how do you go about resolving this using the Windsor Container after registering it? (I registered it through Global.asax). So when you make a request such as "http://localhost/MyService.svc", How do I go about resolving "MyService" instance? How and where could I intercept to provide an instance from Windsor container?

Have a look at these links. You have to add a few classes to hook in to the service factory. These examples are for Unity but I easily modified them for Castle Windsor:
http://initializecomponent.blogspot.com/2008/06/integrating-unity-with-wcf.html
http://initializecomponent.blogspot.com/2008/06/unity-wcf-and-iis.html

Related

How to use UseLoggerFactory in conjunction with UseInternalServiceProvider

We have an asp.net core Web API and registering our EF DB context like so
services
.AddDbContext<SiteDbContext>((serviceProvider, opt) =>
{
opt
.UseNpgsql(options.Site)
.UseInternalServiceProvider(serviceProvider)
;
})
The DB Context calls DbContextOptionsBuilder.UseLoggerFactory which fails.
Looking at this doco https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbcontextoptionsbuilder.useloggerfactory?view=efcore-5.0
It is mentioned that you can't do what I just did above and suggested to "In this case, the ILoggerFactory should be configured directly in that service provider."
My question is how is that specifically done? to configure directly in that service provider.
From the docs (emphasis mine):
Sets the IServiceProvider that the context should resolve all of its services from. EF will create and manage a service provider if none is specified.
The service provider must contain all the services required by Entity Framework (and the database being used). The Entity Framework services can be registered using an extension method on IServiceCollection. For example, the Microsoft SQL Server provider includes an AddEntityFrameworkSqlServer() method to add the required services.
You shouldn't try to replace the internal service provider with the app-level service provider unless you register every single internal service EF core needs.
If you actually need to set the logger factory, there's an easier way to configure it. Use an overload that gives you an IServiceProvider:
services.AddDbContext<AppDbContext>((provider, options) =>
{
var loggerFactory = provider.GetRequiredService<ILoggerFactory>();
options
.UseNpgsql(/* ... */)
.UseLoggerFactory(loggerFactory);
});

Issue in LightInject when getting service instance

I have integrated Light Inject in web api project. I am able to register service successfully in application_start in global.asax. I am using filter which needs to be registered as well in application_start in global.asax. Filter constructor have reference to the services registered however I am not able to get the service instance. Samplee code:
service registration is as below:
container.Register<ILogger, EPPSLogger>(GetLifetime());
filter registration needs instance of ILogger. Using below code:
config.Filters.Add(new EPPSAuthenticationFilter(
config.DependencyResolver.GetService<ILogger>(),
config.DependencyResolver.GetService<IAuthenticationSecrets>()));
gets the error when try to getService that lightinject module is not injected/registered. I cant upgrade to .net framework 4.5 or so.
Any help is highly appreciated.
Thanks

Angular 2 service startup

Is it possible to execute a service in angular 2 at startup?
bootstrap does not execute the service's contstructor.
And also, the injector is executing the service's contstructor each time there is an injection of the service in some component. is there a way to make the service singelton and make sure the ctor will run only once?
Add the service only to bootstrap and not to proiders in your components.
If you inject it in your AppComponent it will be instantiated and only once.
Adding the service to providers on a component creates a new instance for each component instance.
Bootstrap won't start the service, a consuming class that is injecting the service will. By listing it in bootstrap you will get singleton.
If you follow the convention of listing your injectable services (LogRepository) into the bootstrap, then all services will be singleton. (As in LogRepository)
bootstrap(TheApp, [HTTP_PROVIDERS,LogRepository]);
You can get more instances of injectable services if you list them as providers on a component but starting out, just list them in the bootstrap(). All singleton then.

Windsor Ioc Auto Register Classes namespace collision for duplicate type across assemblies

I would like suggestions on if this usage is possible with Windsor and how to achieve. The details (simplified to illustrate the issue) are as follows.
AssemblyA namespace com.foo
IRepository<T>
AssemblyB namespace com.foo
Repository<Data> extends IRepository<Data>
Service -> Resolves Repository<Data> via Windsor
AssemblyC namespace com.foo
Repository<Data> extends IRepository<Data>
Service -> Resolves Repository<Data> via Windsor
AssemblyB references AssemblyA
AssemblyC references AssemblyA
Services are deployed in WCF as follows:
<add relativeAddress="v1/Service.svc" service="com.foo.Service, AssemblyB" />
<add relativeAddress="v2/Service.svc" service="com.foo.Service, AssemblyC" />
Registered via Windsor as follows:
var allTypesFromBinDir =
Classes.FromAssemblyInDirectory(
new AssemblyFilter(path));
Container.Register(allTypesFromBinDir.BasedOn(typeof(IRepository<>))
.WithService.Base()
.LifestyleTransient());
What I want is to scope registration to include the Assembly in qualifying Data for registering and resolving. What occurs is the first assembly scanned AssemblyB registers IRepository with assemblyB.Data and does not register AssemblyC IRespository with assemblyC.Data.
The following occurs or vice versa depending on order dll's scanned.
AssemblyB resolves correctly.
AssemblyC fails to resolve with "No component for supporting the service"
Container.Resolve(IRepository<Data>)
So it seems that the registration treats the two namespaces as the same from registration purpose but resolving takes assembly into account? I expect Registration to take assembly qualification into account as well.
In otherwords...
Windsor "should" I think:
Register AssemblyA.IRepository<AssemblyB.Data> with AssemblyB.Repository<AssemblyB.Data>
And
Register AssemblyA.IRepository<AssemblyC.Data> with AssemblyC.Repository<AssemblyC.Data>
Then Windsor "should" I think:
AssemblyB Service resolves AssemblyA.IRepository<AssemblyB.Data> to AssemblyB.Repository<AssemblyB.Data>
And
AssemblyC Service resolves AssemblyA.IRepository<AssemblyC.Data> to AssemblyC.Repository<AssemblyC.Data>
Instead
Windsor is:
Register AssemblyA.IRepository<AssemblyB.Data> with AssemblyB.Repository<AssemblyB.Data>
And
Does not Register AssemblyA.IRepository<AssemblyC.Data> with AssemblyC.Repository<AssemblyC.Data> I believe it matches AssemblyA.IRepository<Data> from prior registration ignoring Assembly.
Then Windsor is:
AssemblyB Service resolves AssemblyA.IRepository<AssemblyB.Data> to AssemblyB.Repository<AssemblyB.Data>
And
AssemblyC Service does not resolve AssemblyA.IRepository<AssemblyC.Data> but throws component not found. If AssemblyC is scanned first then the exception happens in AssemblyB Service.
I have looked at posts demonstrating something close to what I want by Krzysztof here using IGenericServiceStrategy
However, this strategy seems to work only with Component registration using implemented by.
Thanks in advance.
Having the same namespaces and types in different assemblies is not a good choice. It requires additional job anyway to resolve them withing your clients - extern alias <name>.
extern alias v2Alias;
extern alias v1Alias;
And it seems that when your types in the same namespace then either only types from first assembly are registered:
container.Register(Types.FromAssemblyNamed("v1.com.foo").BasedOn(typeof(IRepository<>)).WithService.Base());
container.Register(Types.FromAssemblyNamed("v2.com.foo").BasedOn(typeof(IRepository<>)).WithService.Base());
or exception 'There is already a component with that name. Did you want to modify the existing component instead? If not, make sure you specify a unique name.' is thrown:
container.Register(Component.For<IRepository<v1Alias::com.foo.Data>>().ImplementedBy<v1Alias::com.foo.Repository>());
container.Register(Component.For<IRepository<v2Alias::com.foo.Data>>().ImplementedBy<v2Alias::com.foo.Repository>());
If you put different versions of your types into different namespaces (e.g. com.foo.v1, com.foo.v2) all your types will be registered.
There'll be no difference how you register them:
container.Register(Component.For<IRepository<v1.com.foo.Data>>().ImplementedBy<v1.com.foo.Repository>());
container.Register(Component.For<IRepository<v2.com.foo.Data>>().ImplementedBy<v2.com.foo.Repository>());
or
container.Register(Types.FromAssemblyNamed("v1.com.foo").BasedOn(typeof(IRepository<>)).WithService.Base());
container.Register(Types.FromAssemblyNamed("v2.com.foo").BasedOn(typeof(IRepository<>)).WithService.Base());
PS: If this solution doesn't work for you then you can post an issue on GitHub or create a pull request with your fix.

How to programmatically un/register POJOs as services in JBoss 4.2.3.GA

I need to be able to circumvent the whole deployer malarkey and programmatically register/unregister (dependency-less) POJOs as services in JBoss.
Currently I'm dynamically creating an MBean interface and registering this with the JBoss MBeanServer, and then registering local/remote with Jndi.
This works ok (I can have a standard service from a vanilla SAR reference one of these service POJOs with the #EJB annotation) - however the container seems to leaves stale references behind as after calling unbind() and unregisterMBean().
Obviously I'm missing something by not dealing with the container in a way it expects, but what am I missing? Or is there an easier way (can't see much in the way of an API)?
thanks.