Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way I can enforce a method to follow certain method signature?

let's say I have

public delegate DataSet AutoCompleteDelegate(
      string filter, long rowOffset);

can I make the following class to enforce that method signature? (just a conjured up idea):

public class MiddleTier
{
    [Follow(AutoCompleteDelegate)]
    public DataSet Customer_AutoComplete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }

    [Follow(AutoCompleteDelegate)]
    public DataSet Item_AutoComplete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }



    // this should give compilation error, doesn't follow method signature
    [Follow(AutoCompleteDelegate)]
    public DataSet BranchOffice_AutoComplete(string filter, string rowOffset)
    {
        var c = Connect();
        // some code here
    }         

}

[EDIT]

Purpose: I already put attributes in my middletier's methods. I have methods like this:

public abstract class MiddleTier : MarshalByRefObject
{
    // Operation.Save is just an enum

    [Task("Invoice", Operation.Save)]
    public Invoice_Save(object pk, DataSet delta);

    [Task("Receipt", Operation.Save)]
    public Receipt_Save(object pk, DataSet delta);


    // compiler cannot flag if someone deviates from team's standard
    [Task("Receipt", Operation.Save)]
    public Receipt_Save(object pk, object[] delta); 
}

then on runtime, i'll iterate all the middletier's methods and put them to collection(attributes helps a lot here), then map them on winform's delegate functions(facilitated by interface, plugins-based system) as loaded

I'm thinking if I can make the attributes more self-describing, so the compiler can catch inconsistencies.

namespace Craft
{        
    // public delegate DataSet SaveDelegate(object pk, DataSet delta); // defined in TaskAttribute

    public abstract class MiddleTier : MarshalByRefObject
    {

        [Task("Invoice", SaveDelegate)]        
        public abstract Invoice_Save(object pk, DataSet delta);

        [Task("Receipt", SaveDelegate)]
        // it's nice if the compiler can flag an error
        public abstract Receipt_Save(object pk, object[] delta);
    }
}

I'm thinking if putting the methods on each class, it would be an overkill to always instantiate a Remoting object. And putting them on separate class, it could be harder to facilitate code reuse, let's say Invoice_Save need some info on Receipt_Open. In fact I even have a report here(crystal), which fetched data from Remoting middletier DataSet, inside the invoked method, it gets some info on other methods and merge in its own DataSet, they are all happening on middletier, no several roundtrips, all are done on server-side(middle-tier)

like image 591
Hao Avatar asked Jun 29 '09 06:06

Hao


3 Answers

Other answers are obviously valid but nothing will guard you against forgetting to apply [Follow(AutoCompleteDelegate)] attribute on your method.

I think you would be better off making turning methods into classes that implement an interface:

public interface IAutoComplete
{
    DataSet Complete(string filter, long rowOffset);
}

public class CustomerAutoComplele : IAutoComplete
{
    public DataSet Complete(string filter, long rowOffset)
    {
        var c = Connect();
        // some code here
    }
}

and then use the factory method pattern to get your "auto completers":

public static class AutoCompleteFactory
{
    public static IAutoComplete CreateFor(string purpose)
    {
        // build up and return an IAutoComplete implementation based on purpose.
    }
}

or

public static class AutoCompleteFactory
{
    public static IAutoComplete CreateFor<T>()
    {
        // build up and return an IAutoComplete implementation based on T which
        // could be Customer, Item, BranchOffice class.
    }
}

Once you have that you could have a look at inversion of control and dependency injection to avoid hard coding the list of auto complete implementations in your factory method.

like image 106
Robert Wilczynski Avatar answered Nov 15 '22 04:11

Robert Wilczynski


You could implement both the FollowAttribute you use in your example and write a Static Analysis (say, FxCop) rule that could check if any method that is tagged with that attribute has the same signature as the mentioned delegate. So it should be possible.

like image 24
peSHIr Avatar answered Nov 15 '22 04:11

peSHIr


This isn't a language feature, but...

This is something you could do validation for: write unit tests that reflect over the class and fail if the signature doesn't match the attribute declaration.

PostSharp also gives you some interesting options for doing this around compilation. I don't know how exactly you would use it, but I suspect you could...

like image 31
Nader Shirazie Avatar answered Nov 15 '22 02:11

Nader Shirazie