How to configure BsonSerializer without use of static registry? - c#

Within a C# project we currently use static methods on BsonSerializer to register serializers for specific types. This happens once on app startup.
However, our acceptance tests start the app up before every test and shut it down after every test, and the second time the app starts up it fails when RegisterSerializer is called, as the registration from the previous test is still in the registry as it's a global static.
Is there any way to register serializers without relying on global statics? Or another strategy for avoiding this problem when running tests?

If you're using the MongoDB serializer, you could check if the serializer is already registered before registering it:
if(BsonSerializer.LookupSerializer<YourCusomType>().GetType() != typeof(YourCusomTypeSerializer))
{
BsonSerializer.RegisterSerializer(new YourCusomTypeSerializer());
}
If you go down this route you should take into account multithreaded scenarios, the above code is not thread safe.
Another option would be to register your own provider and skip the individual serializer registrations:
public class YourCustomSerializationProvider : IBsonSerializationProvider
{
public IBsonSerializer GetSerializer(Type type)
{
if (type == typeof(YourCusomType)) return new YourCusomTypeSerializer();
// fall back to Mongo's defaults
return null;
}
}
// Where you previously registered individual serializers you will now register your provider instead
BsonSerializer.RegisterSerializationProvider(new YourCustomSerializationProvider());
This approach would be a bit more IoC friendly and would give you a bit more control.

Can you register these serializers in static constructor? This way you can call it any number of times you want, the static constructor will not execute more than once.
public class BsonSerializerRegisterer
{
static BsonSerializerRegisterer()
{
BsonSerializer.RegisterSerializer(typeof(DateTime), new DateTimeSerializer(DateTimeKind.Utc));
BsonSerializer.RegisterSerializer(typeof(decimal), new DecimalSerializer(BsonType.Decimal128));
BsonSerializer.RegisterSerializer(typeof(decimal?), new NullableSerializer<decimal>(new DecimalSerializer(BsonType.Decimal128)));
BsonSerializer.RegisterSerializer(new EnumSerializer<MyAwesomeEnum>(BsonType.String));
}
public static void RegisterSerializers()
{
}
}
And then call:
BsonSerializerRegisterer.RegisterSerializers()

A nice article that can help any future readers
https://www.mydevhub.com/mongodb/adding-custom-type-converter-to-mongodb-in-c/
My solution was to add all BsonSerializer.* invokations in the static constructor of StartUp.cs

Related

Passing object of class defined in assembly1 to assembly2, without changing assembly1

I am trying to create tools for a game to learn, as well as improve my own playing experience.
The primary .NET assembly, csass.dll, that controls the client is heavily obfuscated, and I have no control over this .dll-file at all and reading it's code is very time consuming. The game also includes a mainapi.dll which handles the communication between server and client. I have full control over this assembly and I can listen to the servers responses and send my own requests, which already gives me some pretty nice functionality, however there are some limitations I'd like to work around.
csass.dll references mainapi.dll, by default mainapi does not reference csass. In csass.dll there is a class, let's call it clickHandler, that has a public, non-static method ClickObj() of return type void. I want to call this method from within mainapi.dll, but I have no idea how to go about this, given that I have to leave csass.dll untouched.
Are there any feasible ways to 'retrieve' a clickHandler object (to then call its ClickObj() method) from within the mainapi assembly, without making any changes in csass.dll? Appreciate any and all input!
Create an interface:
public interface IClickHandler
{
void ClickObject();
}
Now create a helper class implementing that interface:
using CsAss;
public class ObjectClicker : IClickHandler
{
CsAss _csass;
public ObjectClicker(CsAss csass)
{
_csass = csass;
}
public void ClickObject()
{
_csass.clickObject();
}
}
Add a dependency on an instance of the interface into your MainAPI class:
public class MainApi
{
IClickHandler _clickHandler;
public MainApi(IClickHandler clickHandler)
{
_clickHandler = clickHandler;
// Now you have a class that can call the click handler for you
}
}
Now wire it all up:
public void StartupMethod()
{
var csass = new CsAss();
IClickHandler clickHandler = new ObjectClicker(csass);
var main = new MainApi(clickHandler);
// TODO: Start your app now that MainApi is properly configured
}
That last step is the only potentially tricky part, depending on your project layout. You need something that can create an instance of CsAss, MainApi and ObjectClicker. Normally I would solve that with the dependency injection (DI) pattern, either using a framework such as Autofac or so-called "poor man's DI" by manually instantiating from a central startup method. That gets a little more difficult with Unity since there isn't an easily accessible startup point. You could start looking into https://github.com/svermeulen/Zenject and go from there for options.

How to instantiate outside of a constructor?

How to replicate this code with Autofac syntax?
public static class MenuConfig
{
public static void Initialize()
{
var _menuService = DependecyFactory.GetInstance<IMenuService>();
Parameters.Menu = _menuService.Menu();
}
}
Before calling this a "duplicate question" please note that I'm looking for an Autofac command. I CANNOT inject the interface anywhere and then call "Resolve". What I need to is perform an "InstancePerRequest" inline and uninjected so I don't have to do this:
var _service = new Service(new Dependency(new context()));
LightInject has a method that allows instantiation from an interface OUTSIDE of a constructor like this:
var _service = DependecyFactory.GetInstance<IService>();
What is the equivalent method for Autofac?
When calling containerBuilder.Build() you get back a container which implements IContainer and ILifetimeScope, whenever you get hold of one of these interfaces, you can resolve types from it:
container.Resolve<IService>();
If you want this container to be static, you could add the container as a static property to the Program or Startup class (depending if you're creating a Console or ASP.NET application).
Remember that the root container will be around for the entire duration of your application, so this can result in unwanted memory leaks when used incorrectly. Also see the warning in the documentation.
Still, it's perfectly possible to do the memory management yourself by resolving an Owned<> version from your interface:
using (var service = Program.Container.Resolve<Owned<IService>>())
{
service.Value.UseService();
}
Anyway, since you mention a static class in the comments, the best solution is to change that into a non-static class and register it as a singleton with Autofac. Then you can inject a Func<Owned<IService>> serviceFactory into that singleton and create/dispose an instance of the service wherever you need it.
using (var service = serviceFactory())
{
service.Value.UseService();
}
This is simply not possible with Autofac. All other solutions involving Autofac will require code refactoring which may potentially break software functionality. So unfortunately, the most elegant and least disruptive solution is this:
var _service = new Service(new Dependency(new context()));
Since this is an edge case addressing only one part of the software, this compromise is acceptable. It would be nice, however, if Autofac implemented this functionality in some future release.

How can I implement static 'test local' data in an NUnit test?

I have a couple thousand NUnit tests for a library, many of which rely on having some statically available 'request context' that is scoped to the request being served and flows across tasks. The library consumer provides an implementation to retrieve the current request context.
I need to implement something to provide this context for our NUnit test project, where the context is scoped to each individual test run; each test run should have it's own object, and I should be able to access it from anywhere during the test.
Initially, I had achieved this using TestContext.Current.Properties and storing my request context there, but with a recent NUnit update, Properties has become read-only.
Is there any replacement that I can use to achieve 'test local' data? i.e. something that's scoped to the current test run, and statically accessible.
Similar issue on github contains the following statement from NUnit developer:
However, it's not intended that you should change the properties of an
NUnit Test, because Test and its derivatives are internal and the
implementation can change. The internal classes allow it because
custom attributes may need to do it, but I recommend that tests avoid
doing it.
And such implementation change has actually happen. Before NUnit 2.6.0, TestContext had Properties bag, but since 2.6.0 it was moved to TestAdapter. You still could access it via TestContext.CurrentContext.Test.Properties however you have no guarantee that this will not change again in the future.
The cleaner way to implement such context accessor is by adding simple holder that will compare current test against the test for which current context instance was created. If those tests do not match it just creates a new context instance and remember current test.
Here is a working sample:
internal static class ContextAccessor
{
private static TestExecutionContext currentRequestTest;
private static RequestContext currentRequestContext;
public static RequestContext Current
{
get
{
var currTest = TestExecutionContext.CurrentContext;
if (currentRequestTest == currTest)
{
return currentRequestContext;
}
currentRequestContext = CreateRequestContext();
currentRequestTest = currTest;
return currentRequestContext;
}
}
public static RequestContext CreateRequestContext()
{
return new RequestContext();
}
}
RequestContext here is your context class. CreateRequestContext() is basically a factory method that creates context. You could put any logic you need for creating new context instance.
Now in the test you could just call ContextAccessor.Current:
[Test]
public void SomeTest()
{
var context1 = ContextAccessor.Current;
var context2 = ContextAccessor.Current;
Assert.AreSame(context1, context2);
}
Sample Project on GitHub

Autofac multithreading issues

I'm trying to use autofac DI in my application. I created a wrapper class to abstract away all the autofac dlls:
FrameworkDependencyResolver : Logger, IFrameworkDependencyResolver
In this class I hold the container builder, and register all my dependencies in the application root. After registering my types I build it and hold the container:
Icontainer _container;
ContainerBuilder _builder
public FrameworkDependencyResolver()
{
_builder = new ContainerBuilder();
}
Deep in my application i want to use the FrameworkDependencyResolver object to resolve protocols and open connections to external applications, therefore I registered this object as IFrameworkDependencyResolver with the following code:
_builder.RegisterInstance(obj).As<T>();
Obj is thr FrameworkDependencyResolver, T is the interface
In my starter thread, I resolve object that takes the FrameworkDependencyResolver in his ctor, and it works perfectly, resolvings are fine, however when I resolve an inner layer(on new thread) that takes the FrameworkDependencyResolver in it's ctor and try to resolve a registered protocol object I face deadlock.
Exmaple:
main:
var rootResolver = new FrameworkDependencyResolver();
rootResolver.RegisterType<IClass3, Class3>(Lifecycles.Singleton);
rootResolver.RegisterType<IClass2, Class2>(Lifecycles.Singleton);
rootResolver.RegisterType<Container, TestContainer>(Lifecycles.Singleton);
rootResolver.RegisterObject<IFrameworkDependencyResolver, FrameworkDependencyResolver>(rootResolver);
rootResolver.BuildContainer();
rootResolver.Resolve<TestContainer>();
Console.ReadKey();
TestContainer code:
public TestContainer(IFrameworkDependencyResolver resolver) : base(resolver){}
protected override void InitializeContainer()
{
_class2 = DependencyResolver.Resolve<IClass2>();
Thread.Sleep(20000);
Console.WriteLine("Container initialize finished");
}
Class2 code:
public class2(IFrameworkDependencyResolver resolver)
{
_resolver = resolver;
var thread = new Thread(startMethod);
thread.Start();
Console.WriteLine("Class2 ctor ended");
}
void StartMethod()
{
_class3 = _resolver.Resolve<IClass3>();
Console.WriteLine("Start method finished");
}
The output of this simple example program is:
Class2 ctor ended
Container initialize ended
Start method finished
Meaning that the thread I created is waiting for the main thread to finish and only than it can resolve. I want to prevent this and make it possible to resolve anytime from every thread. Please help me understand what is causing this.
Thank you
Edit:
The problem is not solved because autofac resolves singletons from the root scope..I believe my problem is similar to the one described here : Autofac resolving a singleton creates a bottleneck
but I don't really understand the solution
Edit 2:
for the bottleneck issue I learned that ctors should not contain logic at all.
I also learned I probably shouldn't pass around my IFrameworkDependencyResolver object and should probably use Func<>.
My application structure:
I have a layer in my application that handles connection requests and for every kind of request creates a different kind of protocol (a different protocol object)
// For example lets say a protocol takes in ctor these 3 services + runtime configuration object:
public Protocol1(IFramingAgent, IFramingAlgorithm, IFramingParser, configObject configuration)
Each service is registered with key because each protocol uses a different one
And here is my terrible class:
public class ProtocolsLayer : Layer
{
private IFrameworkDependencyResolver _resolver;
private IConfigurationService _configService;
public ProtocolsLayer(IFrameworkDependencyResolver resolver, IConfigurationService configurationService)
{
_resolver = resolver;
_configService = configurationService;
}
void HandleConnection1()
{
// What I have at the moment (terrible):
// Resolve the fitting services (All keyed - key is received by the type, Resolve and ResolveWithParameters used here are my wrappers)
var agent = _resolver.Resolve<IFramingAgent>(typeof(Protocol1FramingAgent));
var algo = _resolver.Resolve<IFramingAlgorithm>(typeof(Protocol1FramingAlgorith));
var parser = _resolver.Resolve<IFramingParser>(typeof(Protocol1FramingParser));
// A parameter I get and pass to each protocol at runtime
var protocolConfig = _configService.GetConfig<Protocol1Configuration>();
// Finally resolve the protocol with it's parameters:
protocol = _resolver.ResolveWithParameters<IProtocol>(typeof(Protocol1), new List<object>{
agent, resolver, parser, protocolConfig
});
//...
// Theres gotta be a better way!!
}
void HandleConntection2()
{
// Same as in protocol1
}
void HandleConnection3()
{
// Same as in protocol1
}
}
Take in mind that I don't want references to autofac, meaning I can't use IIndex<> which I heard off.
Thanks!
I made a sample to reproduce your issue : https://dotnetfiddle.net/WOGwoD
If I summarize, your issue is that Autofac Resolve for only thread at a time.
Let take another code sample to reproduce the issue :
class Foo1
{
public Foo1()
{
Console.WriteLine("begin Foo1");
Thread.Sleep(1000);
Console.WriteLine("end Foo1");
}
}
class Foo2
{
public Foo2()
{
Console.WriteLine("begin Foo2");
Thread.Sleep(1000);
Console.WriteLine("end Foo2");
}
}
public class Program
{
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo1>().AsSelf().SingleInstance();
builder.RegisterType<Foo2>().AsSelf().SingleInstance();
IContainer container = builder.Build();
var t1 = Task.Run(() => container.Resolve<Foo1>());
var t2 = Task.Run(() => container.Resolve<Foo2>());
Task.WaitAll(t1, t2);
}
}
The output of this program is the following :
begin Foo1
end Foo1
begin Foo2
end Foo2
If you change the lifetime scope from SingleInstance to InstancePerDependency (the default one) for a single registration, the output will be :
begin Foo1
begin Foo2
end Foo1
end Foo2
We can see that Autofac lock the IContainer for Shared registration while it is activating a Shared registration.
The lock statement is Line 258 of LifetimeScope.cs.
I think this behavior is here to prevent issue with complex dependency graph. ie : What happens if Foo1 has a nested dependency on Foo2 ?
You won't be able to bypass this behavior of Autofac.
To change this behavior, you will need to change the way your code works. A constructor is not intended to take time. I recommend you to change your constructor to do only required things, if some of initialization process takes time I would defer it or refactor the code to ensure that constructor takes only few milliseconds to complete.
I created a wrapper class to abstract away all the autofac dlls
Your core code should not rely on dependency injection component. In your case, it looks like you use the IFrameworkDependencyResolver interface to lazy load component or to have a factory component. You should rely on Lazy<T> of Func<T> instead. See implicit relation type for more information.
I follow the same strategy in my application to wrap DI library with my classes to have ability to change it later on if I need to.
I followed the same approach, with only one difference
in your code you create ContainerBuilder in your class constructor and keep reference to it, this is the problem
instead, you may need remove away the ContainerBuilder instance, and just depend on Autofac.ILifetimeScope as constructor dependency for your FrameworkDependencyResolver, this dependency will be just injected by autofac runtime with correct lifetime scope.
then at any level on your code, you can just depend on FrameworkDependencyResolver as you need
EDIT
after i saw your update, i would recommend that you separate registration of your service from resolving instances, i.e make new class like FrameworkDependencyRegister and keep the other one for resolving and follow the steps answer above
in my opinion abstracting registration might be too much unneeded abstraction, you can just write one method to do this stuff using normal autofac APIs

How can I change part of the composition in MEF after composition?

I've setup my app to have a discoverable security service (ISecurityService) which has a single method IPrincipal GetPrincipal(). Implementers are free to then decide how to get the principal (via domain login, DB etc..). So my app then has parts which do things on startup determined on the roles the user is in, for one example I sections of the interface imported like so:
[Import]
public ISecurityService SecurityService {
get; set;
}
[ImportMany]
public IEnumerable<ISectionPanel> ImportedPanels {
get; set;
}
public ObservableCollection<ISectionPanel> Panels {
get; set;
}
public void OnImportsSatisfied() {
Panels.Clear();
IPrincipal p = Thread.CurrentPrincipal;
foreach (ISectionPanel sp in ImportedPanels.Where(sp => sp.RequiredRole == null || p.IsInRole(sp.RequiredRole))) {
Panels.Add(p);
}
}
Don't concentrate too much on the implementation, this is going to change to annotations later, however, the important thing here that made me crop a gutser was that composition of parts was occurring PRIOR to the security principal being set. What this means is I now have a cat and mouse situation.
I've now solved this by using Lazy<T> on imports which affected the chaining to occur, however if another implementer of a part forgets to use Lazy<T> it may trigger a chained load and cause the app to fail.
What have others used to overcome scenarios such as this?
Previously I had unity which I controlled in a more manual way by simply using RegisterInstance<T>(T t), I've trying to now write apps using the "official" MEF as this comes with the framework and I no longer need to worry about unity.
Ideally what I'd like to be able to do is.
Create parts manually at startup prior composition
Create a composition container manually adding my pre-built parts (like RegisterInstance<T>(T t) in unity
Find remaining parts using the usual methods of composition shown in the docs.
You could initialize your application in two phases:
public static void Main(string[] args)
{
using (var container = new CompositionContainer(...))
{
// phase 1: compose security service and initialize principal
var securityService = container.GetExportedValue<ISecurityService>();
securityService.InitializePrincipal();
// phase 2: compose the rest of the application and start it
var form = container.GetExportedvalue<MainForm>();
Application.Run(form);
}
}
In MEF, what more or less corresponds to RegisterInstance would be the AddExportedValue method. This would work if the host created the security service without using MEF. Since you still want to discover the security service with MEF, something like Wim suggests is probably a good solution.

Categories