Working with Resharper's External Annotation XML Files

Resharper 4.0 has external annotation XML files that you can create to give Resharper more information about your code.  For example, you can tell Resharper that a particular method does not accept a null argument.  For example, the following method does not accept a null argument:

using System;
 
namespace Utility
{
    public static class Text
    {
        public static int GetLength(String text)
        {
            if (text == null) throw new ArgumentNullException("text");
            return text.Length;
        }
    }
}

An external annotation file can be created to inform Resharper of this fact and have it warn you when possible null values are passed as an argument:

            String text = null;
            Utility.Text.GetLength(text);

First, you need to create a directory within the Resharper ExternalAnnotations directory.  This ExternalAnnotations directory is usually in the form of "%SystemDrive%\Program Files\JetBrains\ReSharper\vBuild#\Bin\ExternalAnnotations" for example "C:\Program Files\JetBrains\ReSharper\v4.0.816.4\Bin\ExternalAnnotations".

The directory we need to create is the same name as our assembly (without the extension).  In our case this would be "C:\Program Files\JetBrains\ReSharper\v4.0.816.4\Bin\ExternalAnnotations\Utility".

Next, we need to create an XML file to contain the information required by Resharper.  The name of this file is the same as the directory name, plus ".xml".  So, the full file name would be "C:\Program Files\JetBrains\ReSharper\v4.0.816.4\Bin\ExternalAnnotations\Utility\Utility.xml".  This file essentially has an assembly element with child member elements that provide meta-data about methods and arguments.  In our case we want to tell Resharper that the Utility.Text.GetLength(String) method does not accept null values for the argument named "text".  To do this we populate the file with the following XML:

<?xml version="1.0" encoding="utf-8" ?>
<assembly name="Utility">
    <member name="M:Utility.Text.GetLength(System.String)">
        <parameter name="text">
            <attribute ctor="M:JetBrains.Annotations.NotNullAttribute.#ctor" />
        </parameter>
    </member>
</assembly>

After restarting Visual Studio, Resharper will now warn that "text", when passed to GetLength, in the following code, has a "Possible 'null' assignment to entity marked with "NotNull" attribute".

            String text = null;
            Utility.Text.GetLength(text);

I've tried this with the GA build and with both Visual Studio 2005 (SP1) and Visual Studio 2008.

For more information about the annotation options, search for AssertionConditionType in the Resharper help and browse around "%SystemDrive%\Program Files\JetBrains\ReSharper\vBuild#\Bin\ExternalAnnotations" for examples.

Drag-copying in Visual Studio Solution Explorer.

NOTE: I've tried this in Visual Studio 2008 (VS2k8), I'm assuming the same thing happens in Visual Studio 2005 (VS2k5).

In the process of refactoring, it's *very* common for me to rename a type.  This is most easily done by renaming the file in the Solution Explorer (SE)--which renames the file, the type, and and any uses of the type in the entire solution.

Occasionally, I need to create a new type based on another.  Copying an abstract type in order to implement the abstract type is often handy--I just fill in the abstract members (and delete "abstract") in the copied type after renaming it.

Drag-copy in the SE seems like it would take care of a couple of steps at once for me: make a copy and rename it.  Unfortunately it doesn't do that.  It makes a copy of the file (as "Copy of typename.xx") but doesn't rename any types in the class that match the file name.

This might seem somewhat trivial... I can simply rename the file name then refactor rename the type in the file so that the type and all it's constructors are renamed in one fell swoop.  Alas, this simply opens a can of worms that can completely confound a newcomer and annoy an expert.

That simple, intuitive method of renaming a copy of a file then the type within the file actually renames *all* types of that name.  Since we've just made a copy of the type, that means it's always going rename types in two files.  The side-effect of drag-copy in SE means you *must* manually rename the type in the file you just copied.  You can do this with search-replace; but that's friction I don't want and really makes SE drag-copy unusable.

I've logged a bug about it on Connect; but the olde "by design" card was played...

Excellent Overview of Domain-Driven Design and Why it Helps

Deep-fried Bytes has a podcast with David Laribee where they chat about Domain-Driven Design (DDD), some of it's fundamental principles and patterns.  It's part one of two; but, It's an excellent overview of DDD and why it helps.

Posted by PeterRitchie | with no comments

Nested Types

Recently Michael Features blogged about nested types.  The title was almost "nested types considered harmful".

I don't agree.  I don't agree that they're any more harmful than any other C# construct (except goto...).  Nested types are like anything else in our tool-belt: they have a time and place and can be abused.

But, when to use them?  Well, for the most part I agree with Michael, you should avoid them. But, there are times when they're simply the best solution in a given set of circumstances.

Let's look at asynchronous programming model (APM) in .NET.

        // Paraphrased from MSDN
        // Accept one client connection asynchronously.
        public static void DoBeginAcceptTcpClient(TcpListener
            listener)
        {
            // Start to listen for connections from a client.
            Trace.WriteLine("Waiting for a connection...");
 
            // Accept the connection. 
            // BeginAcceptSocket() creates the accepted socket.
            listener.BeginAcceptTcpClient(
                DoAcceptTcpClientCallback,
                listener);
        }
 
        // Process the client connection.
        public static void DoAcceptTcpClientCallback(IAsyncResult ar)
        {
            // Get the listener that handles the client request.
            TcpListener listener = (TcpListener)ar.AsyncState;
 
            // End the operation and display the received data on 
            // the console.
            TcpClient client = listener.EndAcceptTcpClient(ar);
 
            // TODO: do something with client.
 
            // Process the connection here. (Add the client to a
            // server table, read data, etc.)
            Trace.WriteLine("Client connected completed");
        }
 

In this simple scenario we are getting by with a state of simply a TcpListener object.  In a more complex scenario, you'll likely also want a connection-specific queue, some sort of information about what to do after a connection, etc.  While you can use existing types of have several collection instance fields to keep track of each of these things; you then have to introduce synchronization of those collections, managing the content of those collections, etc.--it's much easier and safer to send that information on the stack.  One method I've tried is simply passing an Object collection as the state; but that quickly becomes hard to manage because of the lack of type-safety on the elements in the array (if I remove an element and replace it with another type, the compile can't know and I'll get a run-time error instead of a compile-time error).  To get type safety I generally introduce a new type to aggregate all the types I need in this asynchronous callback.  While this new type *could* be reusable by other classes; it likely isn't and I don't want to then be bound that that explicit contract I've signed by making the types publicly available.  The only option of not making them publicly available is as private nested types.  For example:

        private class AcceptTcpClientParameters
        {
            public CommandQueue CommandQueue { get; private set; }
            public Command NextCommand { get; private set; }
            public TcpListener TcpListener { get; private set; }
 
            public AcceptTcpClientParameters(int commandQueue, int nextCommand, TcpListener tcpListener)
            {
                CommandQueue = commandQueue;
                NextCommand = nextCommand;
                TcpListener = tcpListener;
            }
        }
 
        // Accept one client connection asynchronously.
        public static void DoBeginAcceptTcpClient(TcpListener
            listener, CommandQueue commandQueue, Command nextCommand)
        {
            // Start to listen for connections from a client.
            Trace.WriteLine("Waiting for a connection...");
 
            // Accept the connection. 
            // BeginAcceptSocket() creates the accepted socket.
            listener.BeginAcceptTcpClient(
                DoAcceptTcpClientCallback,
                new AcceptTcpClientParameters(commandQueue, nextCommand, listener));
        }
 
        // Process the client connection.
        public static void DoAcceptTcpClientCallback(IAsyncResult ar)
        {
            AcceptTcpClientParameters parameters = ar.AsyncState as AcceptTcpClientParameters;
            if(parameters == null) return;
 
            TcpClient client = parameters.TcpListener.EndAcceptTcpClient(ar);
 
            parameters.NextCommand.Process(parameters.CommandQueue, client);
        }

I find this use of nested types to be more object-oriented (the needs of the DoAcceptTcpClientCallback are abstracted), more intention revealing, better implements Single Responsibility Principle (SRP), better separates concerns, more maintainable and more agile.

Now, to be clear; this is forced set of circumstances.  You're using a library that implements the APM (right?  You haven't implemented APM yourself...).  But, that's my point--nested types are almost essential in a given set of circumstances.

kick it on DotNetKicks.com 

Sandcastle Source Code Published

The source for the Sandcastle project has been published.  This is great news.

For more information, see http://www.codeplex.com/Sandcastle/SourceControl/ListDownloadableCommits.aspx.

Received Microsoft MVP Award in C# Again

It appears my involvement in the technical communities over the past year have caused me to be re-awarded Microsoft MVP C# for a third year.

Posted by PeterRitchie | 1 comment(s)
Filed under: ,

Comparing CodeRush Refactor! Pro and Resharper 4, part 1 or N -- first glance.

Metadata view of code in referenced assemblies
This is a big one for me.  For whatever reason, Refactor 4 (and prior) completely disables this and sends you to the Object Browser instead.   You get metadata view with CodeRush Refactor! Pro. 

Keyboard layout
As you might imagine, CodeRush Refactor! Pro and Resharper had completely different keyboard layouts.  So, if you're used to R# then Refactor! Pro will take a bit of getting used to.

One thing I don't like with the default Refactor! Pro keyboard layout, is they've replaced Ctrl-. with Quick Navigation.  I use Ctrl-. (instead of Shift-Alt-F10 to get at the smart-tag menu).  Shift-Alt-F10 for smart-tag menu seems more common; so I'll have to get use to Shift-Alt-F10.

Refactor! Pro's Editor enhancements
R# doesn't change to how the editor looks as much as CodeRush Refactor! Pro.  It has the Marker Bar, error/warning/info colouring, and action light-bulbs.  Refactor! Pro with CodeRush has many more, like region painting, flow-break evaluation, Visibility Icons, structural highlighting, etc.

Real-time analysis
Both R# and CodeRush Refactor! Pro do real-time code analysis.  R# has text colouring and the right-hand marker bar.  CodeRush Refactor Pro has a marker bar on both the left and the right.  The left marker bar in CodeRush Refactor! Pro highlights issues for each line, and the right (as does R#) shows a file-wide view of issues.  I find the R# marker bar sometimes doesn't align with the scroll bar so that an issue may be beside the scroll-bar in the marker bar but is actually scrolled off the screen.  CodeRush Refactor Pro doesn't do that and in fact shows the visible portion of the document in its marker bar.  i.e. the marker bar is beside the Visual Studio Indicator Margin (where the breakpoint bullets appear).

Refactorings
They both have many of the same refactorings.  When it comes to non-refactorings the two sometimes approach things differently.  For example R# deals with adding members to a class through "Generate Code" list; whereas CodeRush Refactor Pro uses templates.  E.g. in R#, to add a constructor you hit Alt-Ins and select Constructor.  With Refactor you simply enter "cc "(that 'c', 'c', space).

Smart-Tags
Both approach smart-tags slightly differently.  With R# they use the actions light-bulb at the left margin.  This includes fixes for warnings, errors, plus refactorings, but doesn't include code generation options.  CodeRush Refactor Pro uses an ellipsis-like icon that appears right at the site of the potential refactoring. Code Refactor Pro is a richer experience.  It will show you the result of a refactoring with arrows showing where things will move, red strike-out showing what will be removed, and highlights for things that will be changed/renamed.

Entity Framework Petition of Vote of Non Confidence

I had intended to be happy simply being a signatory of ADO .NET Entity Framework Vote of No Confidence.  But, there's people suggesting signatories of this petition are wackos or on the fringe.

Do yourself a favour and read the petition.  Read what we have issues with and how we think Entity Framework (EF) can be improved to be a better product.  Read seminal material by industry leaders on entity-oriented and object-oriented application development like Domain Driven Design, and Agile Principles, Patterns and Practices in C# (and the predecessor Agile Software Development: Principles, Patterns and Practices) and Applying Domain-Driven Design and Patterns: With Examples in C# and .NET.  If after you have understand this information, you think being forced to use EF on a software development team would mean it would be hard to implement generally accepted object-oriented and entity-oriented design, the sign the petition.

Yes, you have the choice no to use EF; but you also have the choice to help people to not have to deal with the issues detailed in the petition simply because they were not made aware of them.

And despite the naysayers of people who think EF should improve, the ADO.NET team is listening and agrees.

kick it on DotNetKicks.com

Fundamentals of OOD Part 3: Method Cohesion

Single Responsibility Principle (SRP) helps us write more cohesive types and methods.  Cohesion is the relatedness of the members of a type to each other and the relatedness parts of a method's code to other parts.

Method cohesion
Often times a method is not very cohesive, meaning the code that it executes relates to more than one thing.  This can often be seen with a method that contains a large switch statement.  For any invocation of the method only one case statement may be executed; meaning that blocks of code within the method don't relate to all the other blocks.  Switch statements are often an indication that the design should be changed to be more polymorphic or introduce a pattern like the Strategy or Template Method patterns.  Likely a concept of the design is implicit instead of explicit (at least no more explicit than an enum).  For example:

    public class Set {

        public enum Operation {

            Unknown,

            Union,

            Intersection,

            RelativeComplement,

            And,

            Conjunction = And

        }

 

        public static IList<int> PerformOperation(IList<int> one, IList<int> two, Operation operation) {

            List<int> result = new List<int>();

            switch (operation) {

                case Operation.Union:

                    result.AddRange(one);

                    result.AddRange(two);

                    break;

                case Operation.Intersection:

                    foreach (int x in one) {

                        if (two.Contains(x)) {

                            result.Add(x);

                        }

                    }

                    break;

                case Operation.RelativeComplement:

                    foreach (int x in one) {

                        if (!two.Contains(x)) {

                            result.Add(x);

                        }

                    }

                    break;

                case Operation.And:

                    foreach (int x in one) {

                        if (two.Contains(x)) {

                            result.Add(x);

                        }

                    }

                    break;

                default:

                    throw new ArgumentOutOfRangeException("operation");

            }

            return result;

        }

    }

This code works; but it's far from cohesive.  There are many combinations of execution paths this method can take, and each path is unrelated to the other paths.  For example, the Union case has no relation to any of the other cases.  Methods like this are also hard to maintain and prone to errors.  Obviously if another member were added to Operation PerformOperation would have to change--making PerformOperation tightly coupled to Operation--not very object oriented.

This can be made more object-oriented by through Dependency Inversion and the Strategy Pattern:

    public class Set2 {

        public abstract class Operation {

            public abstract IList<int> Execute(IList<int> left, IList<int> right);

        }

 

        public class UnionOperation : Operation {

            public override IList<int> Execute(IList<int> left, IList<int> right) {

                List<int> result = new List<int>();

                result.AddRange(left);

                result.AddRange(right);

                return result;

            }

        }

 

        public class IntersectionOperation : Operation {

            public override IList<int> Execute(IList<int> left, IList<int> right) {

                List<int> result = new List<int>();

                foreach (int x in left) {

                    if (right.Contains(x)) {

                        result.Add(x);

                    }

                }

                return result;

            }

        }

 

        public class RelativeComplementOperation : Operation {

            public override IList<int> Execute(IList<int> left, IList<int> right) {

                List<int> result = new List<int>();

                foreach (int x in left) {

                    if (!right.Contains(x)) {

                        result.Add(x);

                    }

                }

                return result;

            }

        }

 

        public class AndOperation : Operation {

            public override IList<int> Execute(IList<int> left, IList<int> right) {

                List<int> result = new List<int>();

                foreach (int x in left) {

                    if (right.Contains(x)) {

                        result.Add(x);

                    }

                }

                return result;

            }

        }

        public static IList<int> PerformOperation(IList<int> left, IList<int> right, Operation operation) {

            return operation.Execute(left, right);

        }

    }

Now each operation is encapsulated, explicit, PerformOperation need not change as new strategies are added, and we've completely avoided the InvalidOperationException.

kick it on DotNetKicks.com

How Hard Could It Be Indeed: Another sub-standard web site.

Yet another sub-standard website.  I was reading a new Joel Spolsky post today that was a teaser for an article he wrote in Inc. Magazine.  It sounded interesting so I decide to have a read.

 You can imagine my disappointment when this is what I was presented with:

How hard could it be indeed...

Posted by PeterRitchie | with no comments
Filed under:

Spaces or Tabs?

In this day and age it seems silly to get into a discussion about whether your companies coding guidelines should have a section mandating either spaces or tabs for indents.  Tabs are clearly more flexible, but I really don't think it matters at all; people can easily read code that contains spaces or tabs.

But, Microsoft has departed from what seems to be the rest of the world and is mandating spaces in their new Microsoft Source Analysis Tool for C#.

Word is that an update will not only mandate spaces but mandate 4 for indents.

Again, I don't think it's much of an issue; except Microsoft Source Analysis Tool for C# doesn't offer a rule to mandate tabs over spaces.  They're not providing a tool for organizations to use to enforce local coding guidines, but providing a tool to mandate Microsoft's coding guidelines.

The tool can be downloaded here and a discussion on tabs can be found here.

kick it on DotNetKicks.com

Resharper 4.0 EAP Settings and Installing Latest Build

The 4.0 EAP tends to do a full uninstall before installing (it's pre-beta, pre-alpha even; so it's no wonder).

This tends to blow away your settings changes.  If that's a pain point for you, the settings are stored in "%userprofile%\application data\jetbrains\resharper\v4.0\vs9.0".  There are a couple of xml files in there that store your settings.  Before you upgrade to the latest build, just copy those to another directory.

 It's very likely that the format of these files has changed since the last build so copying the backups over the new version could possibly make Resharper to blow-up.  So, use with caution.

Posted by PeterRitchie | 2 comment(s)
Filed under: ,

DevTeach Toronto 2008

Well, DevTeach Toronto 2008 is just wrapping up.  It was a fantastic conference, many world-class developers, world-class presenters, and world-class topic.  Congrats to all.  It was well organized that the tracks that I took part in were well designed.

What's special about conferences like this is the ability to interact with peers and leaders from across our industry, something you can't get any other way.  If you went to the conference and didn't talk to anyone, you really missed out.

The next is DevTeach Montreal in December.  I highly recommend it.

en POCO

First of all, let me describe what a POCO is.

"POCO" is a Plain-Old-CLR-Object.  This means that it does nothing more than be that encapsulated type implemented by that class.  It has SRP and has no other responsibility than that responsibility for which is abstracts.  It has no coupling to other assemblies that are outside of it's responsibility, and ignorant of anything else.  POCO is the .NET side of POJO (Plain-Old-Java-Objects) on the Java side.  POJO was a response to the huge problems that occurred years ago with certain persistence frameworks and a requirement for those classes to know about their own persistence.  POCO is really about Persistence Ignorance (PI); but the practice of SRP and SoC, when followed, result in POCO.

My next statement might see obvious to some; but it's kinda the reason for my post: any class that requires dependencies outside its responsibility to be pulled in isn't a POCO, by definition.  And this includes attributes.

Enter iPOCO. 

So, we've got a term that derives from a Java term (POJO) to specially mean a class that is decoupled from any trappings that aren't part of its behaviour, is completely abstracted and encapsulated.

Prepend an i to the term and you get iPOCO, a term that Microsoft is using as a buzzword for the ability of objects that are used with the Entity Framework (EF) to become presistable with that framework.  A object that is persistable with EF must implement 3 interfaces: IEntityWithChangeTracker, IEntityWithKey, IEntityWithRelationships.  iPOCO is a way to get those interfaces on your class without you having to manually add and implement them, simply by adding an attribute. (it performs some "magic" at build time--and as far as I can tell, is done post compile).

iPOCO is neither more nor less POCO, this is not POCO, it's the opposite of POCO.  Your type is not plain, it's decorated with an attribute.  That object is now coupled to that attribute and all that it brings with it.

That's why POJO/POCO were given a name, to make the practice explicit.  We're writing object-oriented software, it needs to use the basic features of OO: abstraction and encapsulation.

iPOCO == !POCO, If anything it's Persistence Ignorance Ignorance.

 

Posted by PeterRitchie | with no comments
Filed under:

DevTeach 2008

Well, I'm off to DevTeach Toronto 2008.  Track me down and say hi if you're going...

Posted by PeterRitchie | with no comments
Filed under:

RFC: Conditionals on false

Just a small request for comments.  Oren prefers

    if (GetTrueOrFalse() == false)

...instead of

    if (!GetTrueOrFalse())

Coming from 18+ years of C/C++ based language programming, I find either equally readable; but, I'm not always the one reading my code.

What are you thoughts?  Do you prefer the negation operator (!) or explicitly comparing with the false keyword?

Posted by PeterRitchie | 11 comment(s)
Filed under: ,

Fundamentals of OOD, Part 2 - Encapsulation Scope

Let's look at the ubiquitous Person concept.  It might seem logical that an application that deals with people should have a Person interface for classes to implement.  For example:

public interface IPerson
{
                String GivenName { get; set; }
                String SurName { get; set; }
                IAddress Address { get; set; }
}

At first glance this seems fine.  The IPerson interface defines attributes that the application uses with most scenarios dealing with types of IPerson, it's "well encapsulated".  But, the person concept is much more broad than what IPerson is modeling.  IPerson hasn't fully encapsulated the person concept.  A person could have parents, age, weight, height, etc.  The application doesn't need this information so it's narrowed the concept of person to fit its needs. This is an incomplete abstraction.  The type that the application needs (that is currently IPerson) should be fully abstract.  Based on the IPerson interface, a better abstraction would be ILocatableIndividual.

Let's look at the opposite of not fully encapsulating a concept. 

Let's look at another common concept, the Invoice:

public class Invoice
{
                Customer BillToCustomer { get;set; }
                Customer ShipToCustomer { get;set; }
                Datetime InvoiceDate;
                ICollection<InvoiceItem> InvoiceItems { get; }
                Single ShippingAndHandlingPrice { get; set; }
                Single CalculateSubTotal();
                Single CalculateTotal();
                Single CalculateGrandTotal();
                PurchaseOrder PurchaseOrder { get; set; }
                void Print();
}

Again, seems like a reasonable encapsulation; but it has an issue. 

There's a fundamental principle of OOD called the Single Responsibility Principle.  Robert Martin interprets the principle as "there should never be more than one reason for a class to change.".  A class should model a single abstraction.  For that abstraction to remain abstract the modeled class should have a single responsibility.  In the case of Invoice, the invoice concept should only model behaviours and attributes of an invoice.  An invoice does not print, something or someone else prints it.  With the above Invoice definition should printing need to change Invoice must also change, event though what the invoice *is* doesn't change.  Invoice is now coupled to how printing occurs.  In Martin's terms, Invoice now has two reasons for it to change: when invoice attributes change, and when how printing occurs changes. 

The Invoice class should be refactored by moving the Print method to another class.  Likely this would involve MVC, or MVP where a view would be responsible for the "printed view" and a controller or presenter would be responsible for communicating with the model (Invoice).

 

kick it on DotNetKicks.com

Fundamentals of Object-Oriented Design (OOD) Part 1

With increased usage of patterns and situationally specific strategies, people sometimes lose sight of the concepts and principles behind these patterns and strategies and fail to follow them when they're not using patterns or strategies.  I feel it's good to periodically review the fundamental concepts and first principles.

Object Oriented Design (OOD) attempts to help with the complexity of designing, writing, and maintaining software.  It attempts to allow building of software by modeling real-world objects.  As with any tool, it can be used improperly, but OOD attempts to facilitate simplicity, robustness, flexibility, etc..  OOD has many fundamental concepts.  Some of these concepts include modularity, encapsulation, and abstraction.  OOD deals with modeling behaviour and attributes of real-world objects.

Modularity is a technique of composing software from separate parts.  At the lowest level of an Object-Oriented Programming Language (OOPL), this is the definition of a type (a class or a struct in C#/C++).  Depending on the platform there may be various other levels of modularity.  In C#, for example, modularity can occur at other levels like module (source file), namespace, netmodule, assembly, etc.  Modularity is a form of encapsulation.

Encapsulation is a technique of hiding implementation details, grouping them together.  In OOPL, the lowest level of encapsulation is the type level (again, class/struct in C#/C++).  Implementation details (data) is separated from behaviour of a type.  In some OOPLs both behaviour and attributes (properties, for example in C#) are separated from behaviour.  This allows clients to decouple or to be not dependant on those implementation details. Encapsulation is a form of abstraction.

The ability to encapsulate related behaviour, attributes, and implementation allows programmers to utilize abstraction.  Abstraction facilitates separation.  OOPLs allows programmers to keep concepts separate by abstracting them from one another.  Keeping abstract concepts separate allows these concepts to evolve and be used independently.  Properly designed types allow abstraction; a File class can abstract the file system away from a particular file, for example.  The file system is part-and-parcel when dealing with files; but while dealing with a File object, it is abstracted away.

Good OOD has as little dependencies between parts as possible.  This is called lack of coupling.  One part that uses another part means the part depends on that other part.  Changes to the second affect the first.  Good OOD also has parts that contain related behaviour and attributes.  This is called cohesion.  If all the behaviour and attributes are generally used together in each scenario, the part has high cohesion.  If only some behaviour or attributes are used in each scenario, the part has low cohesion and likely should be split up.  Some people only view cohesion and coupling at the class level, I've purposely said "part" because I believe these concepts need to live throughout the modeled system, from class-level details, to modules, to namespace, to assemblies, to layers, to components, to systems, etc.

I will continue this series with the fundamental OOD principles that all good patterns should enforce.

kick it on DotNetKicks.com

Overcoming problems with MethodInfo.Invoke of methods with by-reference value type arguments

I ran into an interesting problem on the Forums recently.  Basically, when you use MethodInfo.Invoke to invoke a method with by-reference value type arguments you can't have the invoked method update a variable/argument.  The problem is, when you invoke the method the parameter is passed to the MethodInfo.Invoke via an object array.  Since we're dealing with a value type, the original value type is boxed and the invoked method actually updates the array element, not the original object (as it would with reference types).  For example:

using System;

using System.Reflection.Emit;

using System.Reflection;

using System.Diagnostics;

 

namespace InvokeTesting

{

    class Program

    {

        private const int testValue = 10;

        public static void TestMethod(ref int i)

        {

            i = testValue;

        }

        static void Main(string[] args)

        {

            MethodInfo methodInfo = typeof (Program).GetMethod("TestMethod", BindingFlags.Static | BindingFlags.Public);

            int i = 0;

            object[] parameters = new object[] {i};

            methodInfo.Invoke(null, parameters);

            // original variable isn't updated

            Debug.Assert(i == 0);

            // array element is updated:

            Debug.Assert((int)parameters[0] == testValue);

 

            // copy updated value to original variable

            i = (int)parameters[0];

 

            Debug.Assert(i == testValue);

        }

    }

}

Of course, the only "workaround" is to get the new value out of the array.

Since essentially we're implementing a run-time method invocation, a "better" way would be to create a dynamic method to make the call.  A dynamic method is a method created at run-time (whose body is generated through ILGenerator.Emit et al) and invoked via a delegate.  For example:

using System;

using System.Reflection.Emit;

using System.Reflection;

using System.Diagnostics;

 

namespace EmitTesting

{

    // delegate for void method that takes one reference parameter

    public delegate void OneRefParameterCallback<T>(ref T value);

 

    class Program

    {

        private const int testValue = 10;

        public static void TestMethod(ref int i)

        {

            i = testValue;

        }

        static void Main(string[] args)

        {

            // create a dynamic method object with arbitrary name "Caller", void return (null), and one parameter "ref int"

            DynamicMethod caller = new DynamicMethod("Caller", null, new Type[] { typeof(int).MakeByRefType() }, typeof(Program).Module);

 

            ILGenerator ilGenerator = caller.GetILGenerator();

 

            // emit ldarg.0

            ilGenerator.Emit(OpCodes.Ldarg_0);

 

            // emit call void EmitTesting.Program::TestMethod(int32&)

            MethodInfo mi = typeof(Program).GetMethod("TestMethod", BindingFlags.Static | BindingFlags.Public, null,

                                                    new Type[] { typeof(int).MakeByRefType() }, null);

            ilGenerator.Emit(OpCodes.Call, mi);

 

            // emit ret

            ilGenerator.Emit(OpCodes.Ret);

 

            OneRefParameterCallback<int> callback =

                (OneRefParameterCallback<int>)caller.CreateDelegate(typeof(OneRefParameterCallback<int>));

 

            // call our emitted code with a reference parameter

            int i = 0;

            callback(ref i);

            Debug.Assert(i == testValue);

        }

    }

}

In this example, the method invocation directly updates a value type variable.  This could be made more re-usable to refactoring the dynamic method creation code into it's own method.

kick it on DotNetKicks.com