tags:

views:

1438

answers:

4

Hello,

I have a static class in a shared project, which I want to extend with further methods in another project. Because the method I want to extend the static class with is only applicable to the 2nd project and also dependent on other classes in that different project, I can't just move it to the shared project.

Basically I have class X in MySolution.SharedProject. I want to create a method X.Get() in MySolution.PrimaryProject which references SharedProject.

It seems that I can't do partial across projects, and I also can't extend static classes using extension methods.

How do I do this??!

For all later visitors: The chosen answer does what I asked, but the BETTER way is what Jon Skeet outlined - choose different class names and get it over with.

+11  A: 

You can't. A type can only exist in a single assembly. (That's why partial types can't be split between projects. The CLR has no concept of partial types - they're just compiler magic to compile a single type from multiple files.)

Why not just create a new type in the second project? Where would the benefit be in "extending" the class?

EDIT: It certainly sounds like you should have two classes, e.g. CommonValidation and ProjectValidation. It should be obvious which methods belong in which class... I really can't see why it would create a problem.

Jon Skeet
Because of taxonomy. I'll slowly kill maintainability of my code if I keep inventing different names for the same thing. F*!!!
Alex
But it's clearly *not* the same thing if one class is only applicable to the second project while the first is more general.
Jon Skeet
Then invent a different namespace instead ;-p Besides; IMO, it (by definition) *isn't* the "same thing".
Marc Gravell
The class I'm talking about handles value validations. However, they are *in part* configurable, but the configuration object is not available in the shared project, only in the primary one. So those methods should only be visible in the primary project, but I still want to re-use the rest as part of my shared library.
Alex
Alex
@Alex: Glad to hear we convinced you in the end :)
Jon Skeet
+3  A: 

You can't use partial classes. You could use inheritance, but then you're not allowed to make the class static, so just make all it's methods static. Then prevent instantiation by making it's constructor protected:

namespace SharedProject
{
 public class X
 {
  protected X() { }
  public static void SharedMethod() { }
 }
}

namespace PrimaryProject
{
 public class X : SharedProject.X
 {
  protected X() { }
  public static void ProjectMethod() { }
 }
}

You'll be able to see both methods when using PrimaryProject.X. Naturally these classes would actually be in different files, and indeed, in different projects.

As Jon pointed out, this can get a little confusing however. Personally I would just use two different class names and no inheritance.

I know, it's a little annoying to come up with names every time, and identifical class names in different namespaces are also somewhat unpractical. If your namespaces are very long, aliasing them locally with the using directive can be of help.

Thorarin
Trying this right now
Alex
That sounds like a recipe for confusion to me, as well as an abuse of inheritance.
Jon Skeet
I'd just use two different class names myself, but *\*shrug\**. I think abuse sounds a bit too harsh, rather it's a workaround for the annoying limitation that static classes can't inherit.
Thorarin
OK so this does what I want it to do. But now you got me a bit unsure of this practice Jon. Maybe I'm getting caught up in something that isn't right.
Alex
Alex
@Thorarin: It's abuse of inheritance because there's no specialization here, which is the purpose of inheritance. The fact that these are naturally static classes which are being made non-static *just to allow inheritance* is a pretty clear indication that inheritance something's wrong, IMO.
Jon Skeet
Who says there is no specialization? Maybe not in my example, but it's possible to specialize certain implementations by using the `new` keyword, and calling the base implementation if needed.
Thorarin
That would go against the original description (where the functionality was wanted in a single type). Adding method hiding ("new" rather than overriding) introduces *yet more* confusion. Sounds like a maintenance nightmare. Compare that with the clean, simple solution of keeping the types separate. No confusion possible at all. It's always obvious what's going to be called, there are no inheritance hierarchies to understand, and classes which are naturally static can *stay* static.
Jon Skeet
+2  A: 

but the configuration object is not available in the shared project, only in the primary one

So those methods should only be visible in the primary project, but I still want to re-use the rest as part of my shared library.

It sounds like you simply want some of the methods to be internal?

public static class Foo
{
    public static void AvailableAnywhere() {...}

    internal static void AvailableForThisAssemblyOnly() {...}
}

If I've misunderstood, then other options include:

  • using an interface to describe the configuration options (so no concrete type in the secondary projects)
  • using [InternalsVisibleTo]
Marc Gravell
No, there's also the dependency issue. As the shared object needs to reside in my shared project, not the primary, I can't put anything dependent on the primary object in it without causing circular reference.
Alex
OK; it was a little unclear whether the "primary" object was *this* dll or a caller. But my point re the interface remains.
Marc Gravell
Additionally, many "circular reference" issues can be avoided with IoC etc.
Marc Gravell
Thanks to you as well for helping me trying to figure this one out!
Alex
A: 

Isn't that the general idea of inheritance, that you have part of your code - the general parts - in one namespace / class, and then the specialized in another? Then it would not make sense to name the namespaces/classes differently.

I have three projects in a solution, divided into a shared "core" project, a smart device project and a win32 project. The code that apply to both platforms are in the core project, the specialized (extends/overwrites) code for smart devices and win32 respectively, simply inherits from the code in the shared core project.

Hence, IMO, there is absolutely nothing wrong with the first answer.

Miros