views:

132

answers:

3

I am in a situation where we need to modify what is being returned from the static repository in a 3rd party open-source application (NopCommerce). The problem is that they use static repositories, so I can't merely inherit an interface and DI my own repository. I'm trying to do this without modifying the NopCommerce code-base... any fresh ideas?

Edit: I want NopCommerce to use my repos, rather than have my code use theirs.

Thanks! Josh

+2  A: 

You could abstract away their stuff by creating an interface of your own and a class implementation that delegates to NopCommerce. Then have your code use the interface instead of directly accessing NopCommerce's classes. You can modify the output of NopCommerce inside your class before the result is returned to your application.

And as an added bonus you could also mock the interface to do some tests that didn't require the full-blown repository implementations.

Something like this, in code:

public interface IRepository 
{
   MyItem GetItem(int id);
}

public class MyNopCommerceWrapper : IRepository
{
   public MyItem GetItem(int id)
   {
       // I have no idea what NopCommerce API looks like, so I made this up.
       var myItem = NopCommerce.GetItem(id);

       ModifyMyItem(myItem);

       return myItem;
   }
}
Anna Lear
I guess I'm trying to wrap my brain around what you're saying here. Essentially we need to modify the way NopCommerce works and what is being returned to NopCommerce. There is no other application. I simply need to modify the repository as if I could DI my own or as if it was marked as virtual and I could override it.
Josh Barker
Looks like it would work, but I would still have to modify NopCommerce to use this wrapper instead of using the static repository, right?
Josh Barker
No. Your application will not know anything about NopCommerce library. It will be wrapped by your wrapper class and your application will only call wrapper's method. Only wrapper will be dependent on NopCommerce. Your application will be able to use DI by injecting wrapper. There is no reason to modify NopCommerce code base - it doesn't need to know about wrapper.
Ladislav Mrnka
I guess I didn't make it clear... there is no other application, there is NopCommerce. If I wanted to take the easy route, I'd just modify the NopCommerce repository directly so that NopCommerce is displaying the information I want. All I am trying to do is filter the data that is being returned *to* NopCommerce. Not to a 3rd party application I am writing.
Josh Barker
By "other application" I meant the application you were writing that used NopCommerce. Your question said you need to modify what's being returned FROM a static repository... and my answer (and Goblin's) would satisfy that.Otherwise, I'm a bit confused as to what you're looking for. Can you expand your question to include some code sketches as an example or something?
Anna Lear
+2  A: 

Sounds like a job for Facade.

Goblin
A: 

We are currently on a really, really tight deadline, and this problem was not forseen. So I am thinking of first starting with a poor man's static interface/poor man's DI like the following (so I don't have to modify the entire solution). Then at a later time, when we are not-so-pressed for time, change over to use an interface and dependency injection and submit a patch to NopCommerce:

// Poor-man's static interface (DI).
public static class OriginalBuiltInStaticClass {
    private static IMyNewClass _myNewClass;

    public static void Inject(IMyNewClass myNewClass) {
        _myNewClass = myNewClass;
        A = _myNewClass.A;
        B = _myNewClass.B;
        C = _myNewClass.C;
    }

    public static Action A = CopySimpleRenameBuiltInStaticClass.A;
    public static Func<int, string> B = CopySimpleRenameBuiltInStaticClass.B;
    public static Action C = CopySimpleRenameBuiltInStaticClass.C;
}

// Original vendor class which was copied and renamed.
public static class CopySimpleRenameBuiltInStaticClass {
    public static void A() {
        Console.WriteLine("OriginalBuiltInStaticClass.A()");
    }

    public static string B(int id) {
        Console.WriteLine("OriginalBuiltInStaticClass.B()");
        return id.ToString();
    }

    public static void C() {
        Console.WriteLine("OriginalBuiltInStaticClass.C()");
    }
}

// Creating an interface to merge into trunk of NopCommerce (convert static repositories)
public interface IMyNewClass {
    void A();
    string B(int id);
    void C();
}

// Implementation of interface.
public class MyNewClass : IMyNewClass {
    public void A() {
        Console.WriteLine("MyNewClass.A()");
    }

    public string B(int id) {
        Console.WriteLine("MyNewClass.B()");
        return id.ToString();
    }

    public void C() {
        CopySimpleRenameBuiltInStaticClass.C();
    }

}

Any thoughts?

Josh Barker
This worked perfectly... I created a T4 template and auto generated the interface, wrapper, and the implementation class. Now, I just place:NopRepo.Inject(new MyExtClass.MyNopRepo());into the Global.asax in Application_Start and viola... DI for static classes.
Josh Barker
For those interested in the T4 template and updates to this code: http://joshbarker.net/?p=33
Josh Barker