Created
February 15, 2018 23:34
-
-
Save SaxxonPike/5e3984644721328347b9e286fa0760f3 to your computer and use it in GitHub Desktop.
Autofac Module
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Reflection; | |
using Autofac; | |
using Module = Autofac.Module; | |
namespace MyGist | |
{ | |
public enum EventChannel | |
{ | |
Draw, | |
Update | |
} | |
[AttributeUsage(AttributeTargets.Class)] | |
public class RegisteredAttribute : Attribute | |
{ | |
public bool AutoDispose { get; set; } = true; | |
public bool IsSingleton { get; set; } = true; | |
} | |
[AttributeUsage(AttributeTargets.Event, AllowMultiple = true)] | |
public class EventSourceAttribute : Attribute | |
{ | |
public EventSourceAttribute(EventChannel channel) | |
{ | |
Channel = channel; | |
} | |
public EventChannel Channel { get; } | |
} | |
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)] | |
public class EventListenerAttribute : Attribute | |
{ | |
public EventListenerAttribute(EventChannel channel) | |
{ | |
Channel = channel; | |
} | |
public EventChannel Channel { get; } | |
} | |
public class MyModule : Module | |
{ | |
private static IEnumerable<Type> GetTypes() | |
{ | |
return typeof(TartModule) | |
.Assembly | |
.GetTypes(); | |
} | |
protected override void Load(ContainerBuilder builder) | |
{ | |
var types = GetTypes(); | |
RegisterAllServices(builder, types); | |
base.Load(builder); | |
} | |
private void RegisterAllServices(ContainerBuilder builder, IEnumerable<Type> types) | |
{ | |
var sources = new Dictionary<EventChannel, List<EventInfo>>(); | |
var registeredTypes = types | |
.Where(t => t.GetCustomAttributes<RegisteredAttribute>().Any()) | |
.ToArray(); | |
foreach (var type in registeredTypes) | |
{ | |
// Collect event sources. | |
foreach (var source in type.GetEvents(BindingFlags.Instance | BindingFlags.Public)) | |
{ | |
var sourceAttributes = source | |
.GetCustomAttributes<EventSourceAttribute>() | |
.ToArray(); | |
if (!sourceAttributes.Any()) | |
continue; | |
foreach (var attribute in sourceAttributes) | |
{ | |
if (!sources.ContainsKey(attribute.Channel)) | |
sources[attribute.Channel] = new List<EventInfo>(); | |
sources[attribute.Channel].Add(source); | |
} | |
} | |
} | |
foreach (var type in registeredTypes) | |
{ | |
// Register all servies marked as registered. | |
var registeredAttribute = type | |
.GetCustomAttributes<RegisteredAttribute>() | |
.Single(); | |
var registrar = builder | |
.RegisterType(type) | |
.AsImplementedInterfaces() | |
.AsSelf() | |
.AutoActivate(); | |
registrar = registeredAttribute.IsSingleton | |
? registrar.SingleInstance() | |
: registrar.InstancePerDependency(); | |
registrar = registeredAttribute.AutoDispose | |
? registrar.OwnedByLifetimeScope() | |
: registrar.ExternallyOwned(); | |
// Add activation handlers for listeners. | |
foreach (var listener in type.GetMethods(BindingFlags.Instance | BindingFlags.Public)) | |
{ | |
var listenerAttributes = listener | |
.GetCustomAttributes<EventListenerAttribute>() | |
.ToArray(); | |
if (!listenerAttributes.Any()) | |
continue; | |
registrar = listenerAttributes.Where(attribute => sources.ContainsKey(attribute.Channel)) | |
.SelectMany(attribute => sources[attribute.Channel]) | |
.Aggregate(registrar, (current, source) => current.OnActivating(activation => | |
{ | |
var sourceInstance = activation.Context.Resolve(source.DeclaringType); | |
var listenerInstance = activation.Instance; | |
source.AddEventHandler(sourceInstance, listener.CreateDelegate(source.EventHandlerType, listenerInstance)); | |
})); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Stick
[Registered]
on your concrete classes only, and get your container like so...And events are automatically connected.