I've successfully implemented a self-hosted WCF service. For legacy matters, the host binding configuration is read from a non-standard source (instead of app.config). When porting this service to IIS, I run into the problem of loading the settings and I found that the solution would involve implementing a class inherited from ServiceHostFactory.
My problem, though, is that the CreateServiceHost method only receives the concrete type and the URI from the SVC file, but I wanted to re-use this class to further implementations and need more information: like the interface that defines the ServiceContract and the binding already configured.
I found this excellent article from #carlosfigueira, but its implementation uses the factory to return a host that is specific to the service, in a 1-to-1 relation. I sure can do it, but that will lead to several specific factories, with lots of copy-and-paste code and I'd ratter avoid it. Is it possible? If so, how can I do it?
There is no built-in way of finding out which contracts are implemented by a service class, but the code shouldn't be too hard. It's something along the lines of the function below. You'll need some logic to determine the relative address if you have multiple contract types (i.e., if you have a single contract, use "", if you have multiple, use the contract name as the address).
private IEnumerable<Type> GetContractType(Type serviceType)
{
if (HasServiceContract(serviceType))
{
yield return serviceType;
}
var contractInterfaceTypes = serviceType.GetInterfaces()
.Where(i => HasServiceContract(i));
foreach (var type in contractInterfaceTypes)
{
yield return type;
}
// if you want, you can also go to the service base class,
// interface inheritance, etc.
}
private static bool HasServiceContract(Type type)
{
return Attribute.IsDefined(type, typeof(ServiceContractAttribute), false);
}
Related
I have a WPF application for which my users can create their own plugins by using MEF. Each plugin implements an interface that allows the main application to perform CRUD operations on some data source, e.g. a database.
I have created 2 plugins:
LocalDatabase - provides data from an SQLite database
RemoteDatabase - provides data from a MySQL database
Both are using Entity Framework to do their job. Each of those plugins needs to have its own implementation of the DbConfiguration class.
Now, the problem is that the WPF application loads those 2 plugins, but fails to assign each of them their own implementation of the DbConfiguration class, because it seems that you can have only one DbConfiguration per AppDomain.
So I always have only one of those plugins working.
I was thinking about having just one implementation of the DbConfiguration class and give each plugin an option to add its required configs to that, but the problem is that it creates some coupling between the WPF application and Entity Framework. I'd like to keep the Entity Framework stuff only inside the plugins without the need of modifying the WPF application. It shouldn't care about what plugins use to access their data source.
Is there any way of making it work this way? Could I maybe somehow create a separate AppDomain per each plugin, so maybe then each could use its own DbConfiguration class?
I've found a solution which is a bit hacky, but it does seem to work, so I thought I'd post it, in an unlikely case that someone would face the same issue somewhere in the future.
After some additional research, I've learnt that you can use the DbConfiguration.Loaded event to register some additional Dependency Resolvers for EF. So, in each plugin's constructor, I subscribe the event and add a new Dependency Resolver: SQLite for the LocalDatabase and MySql for the RemoteDatabase. I got rid of the custom DbConfiguration classes from each plugin.
This looked promising, but actually a new problem appeared - there were cases where LocalDatabase plugin called the MySql resolver and it actually returned the MySql implementation of the requested service type. Obviously the LocalDatabase plugin couldn't work with that, because it expected the SQLite implementation. And vice-versa.
So, each of the Resolvers, would actually need to check who called the GetService method - if it's some method from the same assembly that the custom resolver is in, it tries to resolve. Otherwise it's assumed that a resolver from different plugin should take care of that request and it returns null to actually let it do that.
The problem is that the GetService method doesn't supply any information about the requester. So that's where I came up with the hacky solution, which uses StackTrace to check whether any of the called methods belongs to the same Assembly that the current Resolver resides in.
public class CustomMySqlDbDependencyResolver : IDbDependencyResolver
{
private readonly Assembly _executingAssembly = Assembly.GetExecutingAssembly();
private readonly MySqlDependencyResolver _mySqlResolver = new MySqlDependencyResolver();
public object GetService(Type type, object key)
{
var stackTrace = new StackTrace();
StackFrame[] stackFrames = stackTrace.GetFrames().Skip(1).ToArray();
bool shouldResolve = stackFrames.Any(f => f.GetMethod().DeclaringType.Assembly.Equals(_executingAssembly));
if (!shouldResolve)
{
return null;
}
var resolvedService = _mySqlResolver.GetService(type, key);
return resolvedService;
}
public IEnumerable<object> GetServices(Type type, object key)
{
var service = GetService(type, key);
if (service != null)
{
yield return service;
}
}
}
Using many of the fine examples on this website, I have gotten my WCF service to properly serialize and deserialize concrete objects of interface types across the wire. Unfortunately, why seems to be lacking to me is client support.
A user has retrieved the meta-data from my service and is using that to auto-generate a service reference in visual studio 2012 with "add service reference". They are complaining that in their reference.cs (and thus in their auto-fill tool-tips), interfaces aren't coming across and are replaced by object.
For example, in my service interface code file:
[ServiceKnownType(typeof(ConcreteObject))]
...
[OperationContract]
bool WorkMethod(IMyInterface argument1);
...
but what they see is:
...
[OperationContract]
bool WorkMethod(object argument1);
...
As stated above, my client library works fine because I understand "object" really means "IMyInterface". But this is unclear to another client. How do you force the generated proxy objects to include interfaces, and properly represent the request type?
Thanks in advance!
Edit: Example interface, as per request.
public interface IMyInterface
{
bool DoWork(int i);
string SomeProperty { get; }
}
[DataContract]
[KnownType(typeof(IMyInterface))]
public class ConcreteObject : IMyInterface
{
//Working implementation here.
...
}
I want to access a .NET compiled assembly through RPC (the calling code is Python but that is not really relevant).
The assembly represents an API to a running third-party application (Autodesk AutoCAD, for example). It contains several namespaces which contain static classes which contain API objects. I need to access all kinds of stuff in that object hierarchy: properties, objects, methods and, perhaps most complex, transactions that use IDisposable interface (that essentially means that state, i.e. objects storage, should be maintained between RPC calls).
Rather than continuing to develop my own solution (which uses ZeroMQ messaging and reflection-based call dispatch), I wonder what RPC technology would suit my needs.
I looked into basic examples of popular libraries that implement JSON-RPC and SOAP. I see that these libraries demand that you inherit your callable class from their base classes and put attributes into class declaration, for example
[SoapMethod("RequestResponseMethod")]
in order for RPC to work. Obviously, I cannot do that in the case of an external pre-compiled assembly.
I would like to know if JSONRPC or SOAP are indeed the wrong choice for the task that I described or there actually is a way to make RPC work with an external assembly that I don't know about.
Any guidance, comments or basic advice would be much appreciated since I have no experience using any of the existing RPC technologies.
If you are talking about JSON / SOAP I guess you are using HTTP, which is stateless => you need to supply some kind of "state variable". This can be done via e.g. a cookie or like in my examle:
To access your external API create a "wrapper service" (using WCF or "old-school web-services"):
public class MyApiAccess : IMyApiService
{
private static Dictionary<int, MyAPI> apiInstances = new Dictionary<int, MyAPI>();
public int StartSession()
{
var api = new MyAPI();
int id = api.Id; // or some other way to get an unique id
apiInstances.Add(id, api);
return id;
}
public void EndSession(int sessionId)
{
// ensure "sessionId" is valid
var api = apiInstances[sessionId];
api.Dispose();
apiInstances.Remove(api);
}
public MyType MyMethod(myParameter param)
{
// ensure "sessionId" is valid
var api = apiInstances[sessionId];
return api.MyMethod(param);
}
}
This should give you a starting point how such a service could be implemented.
Using SimpleInjector, I am trying to register an entity that depends on values retrieved from another registered entity. For example:
Settings - Reads settings values that indicate the type of SomeOtherService the app needs.
SomeOtherService - Relies on a value from Settings to be instantiated (and therefore registered).
Some DI containers allow registering an object after resolution of another object. So you could do something like the pseudo code below:
container.Register<ISettings, Settings>();
var settings = container.Resolve<ISettings>();
System.Type theTypeWeWantToRegister = Type.GetType(settings.GetTheISomeOtherServiceType());
container.Register(ISomeOtherService, theTypeWeWantToRegister);
SimpleInjector does not allow registration after resolution. Is there some mechanism in SimpleInjector that allows the same architecture?
A simple way to get this requirement is to register all of the available types that may be required and have the configuration ensure that the container returns the correct type at run time ... it's not so easy to explain in English so let me demonstrate.
You can have multiple implementations of an interface but at runtime you want one of them, and the one you want is governed by a setting in a text file - a string. Here are the test classes.
public interface IOneOfMany { }
public class OneOfMany1 : IOneOfMany { }
public class OneOfMany2 : IOneOfMany { }
public class GoodSettings : ISettings
{
public string IWantThisOnePlease
{
get { return "OneOfMany2"; }
}
}
So let's go ahead and register them all:
private Container ContainerFactory()
{
var container = new Container();
container.Register<ISettings, GoodSettings>();
container.RegisterAll<IOneOfMany>(this.GetAllOfThem(container));
container.Register<IOneOfMany>(() => this.GetTheOneIWant(container));
return container;
}
private IEnumerable<Type> GetAllOfThem(Container container)
{
var types = OpenGenericBatchRegistrationExtensions
.GetTypesToRegister(
container,
typeof(IOneOfMany),
AccessibilityOption.AllTypes,
typeof(IOneOfMany).Assembly);
return types;
}
The magic happens in the call to GetTheOneIWant - this is a delegate and will not get called until after the Container configuration has completed - here's the logic for the delegate:
private IOneOfMany GetTheOneIWant(Container container)
{
var settings = container.GetInstance<ISettings>();
var result = container
.GetAllInstances<IOneOfMany>()
.SingleOrDefault(i => i.GetType().Name == settings.IWantThisOnePlease);
return result;
}
A simple test will confirm it works as expected:
[Test]
public void Container_RegisterAll_ReturnsTheOneSpecifiedByTheSettings()
{
var container = this.ContainerFactory();
var result = container.GetInstance<IOneOfMany>();
Assert.That(result, Is.Not.Null);
}
As you already stated, Simple Injector does not allow mixing registration and resolving instances. When the first type is resolved from the container, the container is locked for further changes. When a call to one of the registration methods is made after that, the container will throw an exception. This design is chosen to force the user to strictly separate the two phases, and prevents all kinds of nasty concurrency issues that can easily come otherwise. This lock down however also allows performance optimizations that make Simple Injector the fastest in the field.
This does however mean that you sometimes need to think a little bit different about doing your registrations. In most cases however, the solution is rather simple.
In your example for instance, the problem would simply be solved by letting the ISomeOtherService implementation have a constructor argument of type ISettings. This would allow the settings instance to be injected into that type when it is resolved:
container.Register<ISettings, Settings>();
container.Register<ISomeOtherService, SomeOtherService>();
// Example
public class SomeOtherService : ISomeOtherService {
public SomeOtherService(ISettings settings) { ... }
}
Another solution is to register a delegate:
container.Register<ISettings, Settings>();
container.Register<ISomeOtherService>(() => new SomeOtherService(
container.GetInstance<ISettings>().Value));
Notice how container.GetInstance<ISettings>() is still called here, but it is embedded in the registered Func<ISomeOtherService> delegate. This will keep the registration and resolving separated.
Another option is to prevent having a large application Settings class in the first place. I experienced in the past that those classes tend to change quite often and can complicate your code because many classes will depend on that class/abstraction, but every class uses different properties. This is an indication of a Interface Segregation Principle violation.
Instead, you can also inject configuration values directly into classes that require it:
var conString = ConfigurationManager.ConnectionStrings["Billing"].ConnectionString;
container.Register<IConnectionFactory>(() => new SqlConnectionFactory(conString));
In the last few application's I built, I still had some sort of Settings class, but this class was internal to my Composition Root and was not injected itself, but only the configuration values it held where injected. It looked like this:
string connString = ConfigurationManager.ConnectionStrings["App"].ConnectionString;
var settings = new AppConfigurationSettings(
scopedLifestyle: new WcfOperationLifestyle(),
connectionString: connString,
sidToRoleMapping: CreateSidToRoleMapping(),
projectDirectories: ConfigurationManager.AppSettings.GetOrThrow("ProjectDirs"),
applicationAssemblies:
BuildManager.GetReferencedAssemblies().OfType<Assembly>().ToArray());
var container = new Container();
var connectionFactory = new ConnectionFactory(settings.ConnectionString);
container.RegisterSingle<IConnectionFactory>(connectionFactory);
container.RegisterSingle<ITimeProvider, SystemClockTimeProvider>();
container.Register<IUserContext>(
() => new WcfUserContext(settings.SidToRoleMapping), settings.ScopedLifestyle);
UPDATE
About your update, if I understand correctly, you want to allow the registered type to change based on a configuration value. A simple way to do this is as follows:
var settings = new Settings();
container.RegisterSingle<ISettings>(settings);
Type theTypeWeWantToRegister = Type.GetType(settings.GetTheISomeOtherServiceType());
container.Register(typeof(ISomeOtherService), theTypeWeWantToRegister);
But please still consider not registering the Settings file at all.
Also note though that it's highly unusual to need that much flexibility that the type name must be placed in the configuration file. Usually the only time you need this is when you have a dynamic plugin model where a plugin assembly can be added to the application, without the application to change.
In most cases however, you have a fixed set of implementations that are already known at compile time. Take for instance a fake IMailSender that is used in your acceptance and staging environment and the real SmptMailSender that is used in production. Since both implementations are included during compilation, allowing to specify the complete fully qualified type name, just gives more options than you need, and means that there are more errors to make.
What you just need in that case however, is a boolean switch. Something like
<add key="IsProduction" value="true" />
And in your code, you can do this:
container.Register(typeof(IMailSender),
settings.IsProduction ? typeof(SmtpMailSender) : typeof(FakeMailSender));
This allows this configuration to have compile-time support (when the names change, the configuration still works) and it keeps the configuration file simple.
I would like to be able to add subscriptions to additional message types living on potentially different servers to my application at runtime. What I'm trying to achieve is a Monitoring application where I can add/remove subscriptions at runtime. Is this possible? How do I get a reference to the current UnicastBus mappings?
Here is what I'm doing so far, but I believe this will overwrite any mappings currently in existence.
MessageEndpointMappingCollection mappings = new MessageEndpointMappingCollection();
mappings.Add(new MessageEndpointMapping()
{
Messages = m.MessageType.ToString(),
Endpoint = m.QueueName
});
IComponentConfig<UnicastBusConfig> busConfig = config.Configurer.ConfigureComponent<UnicastBusConfig>(ComponentCallModelEnum.None);
busConfig.ConfigureProperty(u => u.MessageEndpointMappings, mappings);
Yves used this code in his Azure samples (to be found in NSB samples collection)
using NServiceBus.Config;
using NServiceBus.Config.ConfigurationSource;
namespace OrderService
{
class ConfigOverride : IProvideConfiguration<UnicastBusConfig>
{
public UnicastBusConfig GetConfiguration()
{
return new UnicastBusConfig
{
MessageEndpointMappings = new MessageEndpointMappingCollection
{
new MessageEndpointMapping { Messages="MyMessages", Endpoint="orderserviceinputqueue" }
}
};
}
}
}
The best way to approach this would be to implement IConfigurationSource and provide your own configuration. Then you could cherry pick what you would like to load from the config file (if anything) and what you would like to specify yourself at runtime.
I would reflect the DefaultConfigurationSource class or refer to this gist for guidance.
In a project, I am currently involved with, we are doing some content-based routing to dynamically subscribed/unsubscribed agents by keeping track of them in our own routing table.
We have wrapped the IBus in a decorator (by using Windsor's support of decorators, as described <plug>here</plug>), that sees if the message implements a special IRoutableMessage interface, that allows the decorator to route the message by explicitly specifying the destination endpoint via bus.Send(destinationEndpoint).
This was a little bit complex to get right, and I would recommend going with NServiceBus' built-in routing as far as possible. But is is possible to explicitly route messages to any endpoint.
If you are looking into monitoring, check out the NSBManager repository. This takes the opposite approach and lets the endpoints register with the manager.