Skip to content

Commit

Permalink
Message handler get registered with the container. If the handler cla…
Browse files Browse the repository at this point in the history
…ss is decorated with [SingletonMessageHandler], the handler is registered as a singleton. Otherwise, the message handler is registered per dependency. Handler is instantiated from the container to handle the message so the handler will get dependencies injected automatically. The IsReusable attribute is not needed (or checked) on message handlers. Message handlers no longer require a default constructor.
  • Loading branch information
tcabanski committed Oct 2, 2011
1 parent 33d0b2a commit 5749d89
Show file tree
Hide file tree
Showing 10 changed files with 367 additions and 60 deletions.
324 changes: 324 additions & 0 deletions ProjectExtensions.Azure.ServiceBus.6.0.ReSharper
@@ -0,0 +1,324 @@
<Configuration>
<CodeStyleSettings>
<ExternalPath IsNull="False">
</ExternalPath>
<Sharing>SOLUTION</Sharing>
<CSS>
<FormatSettings />
<Naming2 />
</CSS>
<CSharp>
<FormatSettings>
<ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER>False</ALIGN_MULTILINE_ARRAY_AND_OBJECT_INITIALIZER>
<ANONYMOUS_METHOD_DECLARATION_BRACES>END_OF_LINE</ANONYMOUS_METHOD_DECLARATION_BRACES>
<CASE_BLOCK_BRACES>END_OF_LINE</CASE_BLOCK_BRACES>
<EMPTY_BLOCK_STYLE>TOGETHER_SAME_LINE</EMPTY_BLOCK_STYLE>
<EXPLICIT_INTERNAL_MODIFIER>False</EXPLICIT_INTERNAL_MODIFIER>
<EXPLICIT_PRIVATE_MODIFIER>False</EXPLICIT_PRIVATE_MODIFIER>
<FORCE_IFELSE_BRACES_STYLE>ALWAYS_ADD</FORCE_IFELSE_BRACES_STYLE>
<INDENT_ANONYMOUS_METHOD_BLOCK>False</INDENT_ANONYMOUS_METHOD_BLOCK>
<INDENT_EMBRACED_INITIALIZER_BLOCK>False</INDENT_EMBRACED_INITIALIZER_BLOCK>
<INITIALIZER_BRACES>END_OF_LINE</INITIALIZER_BRACES>
<INVOCABLE_DECLARATION_BRACES>END_OF_LINE</INVOCABLE_DECLARATION_BRACES>
<MODIFIERS_ORDER IsNull="False">
<Item>public</Item>
<Item>protected</Item>
<Item>internal</Item>
<Item>private</Item>
<Item>new</Item>
<Item>abstract</Item>
<Item>virtual</Item>
<Item>override</Item>
<Item>sealed</Item>
<Item>static</Item>
<Item>readonly</Item>
<Item>extern</Item>
<Item>unsafe</Item>
<Item>volatile</Item>
</MODIFIERS_ORDER>
<OTHER_BRACES>END_OF_LINE</OTHER_BRACES>
<PLACE_ABSTRACT_ACCESSORHOLDER_ON_SINGLE_LINE>False</PLACE_ABSTRACT_ACCESSORHOLDER_ON_SINGLE_LINE>
<PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE>False</PLACE_FIELD_ATTRIBUTE_ON_SAME_LINE>
<PLACE_SIMPLE_ACCESSOR_ON_SINGLE_LINE>False</PLACE_SIMPLE_ACCESSOR_ON_SINGLE_LINE>
<SPACE_BEFORE_TYPEOF_PARENTHESES>False</SPACE_BEFORE_TYPEOF_PARENTHESES>
<TYPE_DECLARATION_BRACES>END_OF_LINE</TYPE_DECLARATION_BRACES>
<WRAP_LIMIT>200</WRAP_LIMIT>
</FormatSettings>
<UsingsSettings />
<Naming2>
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
<PredefinedRule Inspect="True" Prefix="_" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateStaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
</Naming2>
<CustomMemberReorderingPatterns><![CDATA[<?xml version="1.0" encoding="utf-8" ?>

<!--
I. Overall

I.1 Each pattern can have <Match>....</Match> element. For the given type declaration, the pattern with the match, evaluated to 'true' with the largest weight, will be used
I.2 Each pattern consists of the sequence of <Entry>...</Entry> elements. Type member declarations are distributed between entries
I.3 If pattern has RemoveAllRegions="true" attribute, then all regions will be cleared prior to reordering. Otherwise, only auto-generated regions will be cleared
I.4 The contents of each entry is sorted by given keys (First key is primary, next key is secondary, etc). Then the declarations are grouped and en-regioned by given property

II. Available match operands

Each operand may have Weight="..." attribute. This weight will be added to the match weight if the operand is evaluated to 'true'.
The default weight is 1

II.1 Boolean functions:
II.1.1 <And>....</And>
II.1.2 <Or>....</Or>
II.1.3 <Not>....</Not>

II.2 Operands
II.2.1 <Kind Is="..."/>. Kinds are: class, struct, interface, enum, delegate, type, constructor, destructor, property, indexer, method, operator, field, constant, event, member
II.2.2 <Name Is="..." [IgnoreCase="true/false"] />. The 'Is' attribute contains regular expression
II.2.3 <HasAttribute CLRName="..." [Inherit="true/false"] />. The 'CLRName' attribute contains regular expression
II.2.4 <Access Is="..."/>. The 'Is' values are: public, protected, internal, protected internal, private
II.2.5 <Static/>
II.2.6 <Abstract/>
II.2.7 <Virtual/>
II.2.8 <Override/>
II.2.9 <Sealed/>
II.2.10 <Readonly/>
II.2.11 <ImplementsInterface CLRName="..."/>. The 'CLRName' attribute contains regular expression
II.2.12 <HandlesEvent />
-->

<Patterns xmlns="urn:shemas-jetbrains-com:member-reordering-patterns">

<!--Do not reorder COM interfaces and structs marked by StructLayout attribute-->
<Pattern>
<Match>
<Or Weight="100">
<And>
<Kind Is="interface"/>
<Or>
<HasAttribute CLRName="System.Runtime.InteropServices.InterfaceTypeAttribute"/>
<HasAttribute CLRName="System.Runtime.InteropServices.ComImport"/>
</Or>
</And>
<HasAttribute CLRName="System.Runtime.InteropServices.StructLayoutAttribute"/>
</Or>
</Match>
</Pattern>

<!--Special formatting of NUnit test fixture-->
<Pattern RemoveAllRegions="true">
<Match>
<And Weight="100">
<Kind Is="class"/>
<HasAttribute CLRName="NUnit.Framework.TestFixtureAttribute" Inherit="true"/>
</And>
</Match>

<!--Setup/Teardow-->
<Entry>
<Match>
<And>
<Kind Is="method"/>
<Or>
<HasAttribute CLRName="NUnit.Framework.SetUpAttribute" Inherit="true"/>
<HasAttribute CLRName="NUnit.Framework.TearDownAttribute" Inherit="true"/>
<HasAttribute CLRName="NUnit.Framework.FixtureSetUpAttribute" Inherit="true"/>
<HasAttribute CLRName="NUnit.Framework.FixtureTearDownAttribute" Inherit="true"/>
</Or>
</And>
</Match>
<Group Region="Setup/Teardown"/>
</Entry>

<!--All other members-->
<Entry/>

<!--Test methods-->
<Entry>
<Match>
<And Weight="100">
<Kind Is="method"/>
<HasAttribute CLRName="NUnit.Framework.TestAttribute" Inherit="false"/>
</And>
</Match>
<Sort>
<Name/>
</Sort>
</Entry>
</Pattern>

<!--Default pattern-->
<Pattern>

<!--public delegate-->
<Entry>
<Match>
<And Weight="100">
<Access Is="public"/>
<Kind Is="delegate"/>
</And>
</Match>
<Sort>
<Name/>
</Sort>
<Group Region="Delegates"/>
</Entry>

<!--public enum-->
<Entry>
<Match>
<And Weight="100">
<Access Is="public"/>
<Kind Is="enum"/>
</And>
</Match>
<Sort>
<Name/>
</Sort>
<Group>
<Name Region="${Name} enum"/>
</Group>
</Entry>

<!--static fields and constants-->
<Entry>
<Match>
<Or>
<Kind Is="constant"/>
<And>
<Kind Is="field"/>
<Static/>
</And>
</Or>
</Match>
<Sort>
<Kind Order="constant field"/>
</Sort>
</Entry>

<!--instance fields-->
<Entry>
<Match>
<And>
<Kind Is="field"/>
<Not>
<Static/>
</Not>
</And>
</Match>
<Sort>
<Readonly/>
<Name/>
</Sort>
</Entry>

<!--Constructors. Place static one first-->
<Entry>
<Match>
<Kind Is="constructor"/>
</Match>
<Sort>
<Static/>
</Sort>
</Entry>

<!--properties, indexers-->
<Entry>
<Match>
<Or>
<Kind Is="property"/>
<Kind Is="indexer"/>
</Or>
</Match>
</Entry>

<!--interface implementations-->
<Entry>
<Match>
<And Weight="100">
<Kind Is="member"/>
<ImplementsInterface/>
</And>
</Match>
<Sort>
<ImplementsInterface Immediate="true"/>
</Sort>
</Entry>

<!--all other members-->
<Entry/>

<!--nested types-->
<Entry>
<Match>
<Kind Is="type"/>
</Match>
<Sort>
<Name/>
</Sort>
</Entry>
</Pattern>

</Patterns>
]]></CustomMemberReorderingPatterns>
</CSharp>
<HTML>
<FormatSettings />
</HTML>
<JavaScript>
<FormatSettings />
<Naming2 />
</JavaScript>
<VB>
<FormatSettings />
<ImportsSettings />
<Naming2>
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
</Naming2>
</VB>
<Web>
<Naming2 />
</Web>
<XML>
<FormatSettings />
</XML>
<Xaml>
<Naming2 />
</Xaml>
<GenerateMemberBody />
<Naming2>
<EventHandlerPatternLong>$object$_On$event$</EventHandlerPatternLong>
<EventHandlerPatternShort>$event$Handler</EventHandlerPatternShort>
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="MethodPropertyEvent" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="TypesAndNamespaces" />
<PredefinedRule Inspect="True" Prefix="I" Suffix="" Style="AaBb" ElementKind="Interfaces" />
<PredefinedRule Inspect="True" Prefix="T" Suffix="" Style="AaBb" ElementKind="TypeParameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Locals" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="LocalConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="Parameters" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PublicFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="PrivateInstanceFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="PrivateStaticFields" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Constants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="PrivateConstants" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="StaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="aaBb" ElementKind="PrivateStaticReadonly" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="EnumMember" />
<PredefinedRule Inspect="True" Prefix="" Suffix="" Style="AaBb" ElementKind="Other" />
</Naming2>
</CodeStyleSettings>
</Configuration>
7 changes: 0 additions & 7 deletions readme.txt
Expand Up @@ -36,13 +36,6 @@ public class TestMessageSubscriber : IHandleMessages<TestMessage> {
public void Handle(TestMessage message, IDictionary<string, object> metadata) {
logger.Log(LogLevel.Info, "Message received: {0} {1}", message.Value, message.MessageId);
}

public bool IsReusable {
get {
return false;
}
}

}


Expand Down
33 changes: 20 additions & 13 deletions src/ProjectExtensions.Azure.ServiceBus/AzureBus.cs
Expand Up @@ -141,34 +141,41 @@ public class AzureBus : IBus {

subscribedTypes.Add(type);

ConstructorInfo ctor = type.GetConstructors().Where(item => item.GetParameters().Count() == 0).First();
var activator = ReflectionHelper.GetActivator(ctor);

//non generic types only for now.
var instance = activator(new object[] { null });
var castProperty = instance.GetType().GetProperty("IsReusable");
var canReuse = (bool)castProperty.GetGetMethod().Invoke(instance, null);
var builder = new ContainerBuilder();

//for each interface we find, we need to register it with the bus.
foreach (var foundInterface in interfaces) {

var implementedType = foundInterface.GetGenericArguments()[0];
var implementedMessageType = foundInterface.GetGenericArguments()[0];
//due to the limits of 50 chars we will take the name and a MD5 for the name.
var hashName = implementedType.FullName + "|" + type.FullName;
var hashName = implementedMessageType.FullName + "|" + type.FullName;

var hash = Helpers.CalculateMD5(hashName);
var fullName = (IsCompetingHandler(foundInterface) ? "C_" : config.ServiceBusApplicationId + "_") + hash;

var info = new ServiceBusEnpointData() {
DeclaredType = type,
IsReusable = canReuse,
MessageType = implementedType,
StaticInstance = instance,
SubscriptionName = fullName
MessageType = implementedMessageType,
SubscriptionName = fullName,
ServiceType = foundInterface,
IsReusable = (type.GetCustomAttributes(typeof(SingletonMessageHandlerAttribute), false).Count() > 0)
};


if (!BusConfiguration.Container.IsRegistered(type)) {
if (info.IsReusable) {
builder.RegisterType(type).SingleInstance();
}
else {
builder.RegisterType(type).InstancePerDependency();
}
}


callback(info);
}

builder.Update(BusConfiguration.Container);
}
}
}

0 comments on commit 5749d89

Please sign in to comment.