Inheritance and the 'Curiously Recurring Template Pattern' - c#

In an MVC project I have the following classes:
public abstract class Browse<T> where T : Browse<T>
public abstract class SqlBrowse<T> : Browse<T> where T : Browse<T>
public class SqlBrowseBoys : SqlBrowse<SqlBrowseBoys>
public class SqlBrowseGirls : SqlBrowse<SqlBrowseGirls>
and the following view model
public class BrowseViewModel
{
public [INTERFACE] People { get; set; }
}
but I need an interface/class in the position labelled [INTERFACE] that can take both SqlBrowseBoys and SqlBrowseGirls so I can use BrowseViewModel in multiple places.
I'd love it if someone could show me how as my brain is now tied in knots. I suspect this will require some change(s) to the classes and that's fine but I currently have no clue what that will be.
Many, many thanks.

Have SqlBrowse<T> implement a non-generic SqlBrowse interface (or abstract class), and then write
public SqlBrowse People { get; set; }
It's hard to tell what changes that will entail to your classes because we don't have their definitions.

Related

How to stop using Protobuf-Net inheritance and use inherited classes directly?

I have an inherited settings classes inherited from a base class which I would like to (de)serialise separately (example)
[ProtoContract]
[ProtoInclude(1, typeof(GlobalSettings))]
[ProtoInclude(2, typeof(UserSettings))]
public class BaseSettings
{
}
[ProtoContract]
public class GlobalSettings: BaseSettings
{
[ProtoMember(1)]
public string TempPath { get; set; }
}
[ProtoContract]
public class UserSettings: BaseSettings
{
[ProtoMember(1)]
public int UILanguage { get; set; }
}
Only issue is I cannot afford losing the configuration, can it be done in a way that if UserSettings are no longer inherited from BaseSettings and moved to another assembly to be used independently, (de)serialisation still will be possible (with some sort of conversion or without) without access to GlobalSettings class?
The inheritance is a fundamental part of the serialization model, especially if you ever talk in terms of Deserialize<BaseSettings>. If you only ever do things like Deserialize<GlobalSettings> or Deserialize<UserSettings>, then you might be able to remove the [ProtoInclude]s, but then the issue becomes announcing the members of BaseSettings into the sub-types. There are ways to do that.

Adding an interface to a partial class

I have a class that is generated by a third party tool:
public partial class CloudDataContext : DbContext
{
// ...SNIPPED...
public DbSet<User> Users { get; set; }
}
I create a partial class and then assign an interface so that I can inject this class later:
public partial class CloudDataContext : IDataContext
{
}
The IDataContext has the single property Users.
This won't compile, the compiler complains that the interface isn't implemented.
If I move the interface to the generated class, it works fine. I can't do that though as it's generated code.
How can I apply an interface to a partial class to expose the class as defined above?
The problem must be somewhere else, because you can implement interface in the other part of partial class than it's set on. I just tried following and it compiles just fine:
public interface IFoo
{
int Bar { get; set; }
}
public partial class Foo
{
public int Bar { get; set; }
}
public partial class Foo : IFoo
{
}
The properties probably use different types in interface and class.
Here's a quick checklist. Do the classes have identical:
Names?
Namespaces?
Access modifiers?
Example:
You decide to split an existing class into two files.
The original file's namespace doesn't match its folder path.
Consequently, the new class file you create has a mismatching namespace.
Build fails.
IN my Case problem was that interface Method that was implemented in other part of the partial class was not compiling and C# was giving error of not implemented Method
In my case, the interface method signature didn't mention a value (uint direction) that the actual method expected. This showed up as the interface having errors in one of the partial classes. Make sure that the interface for a method is actually the same as the method signature itself. D'oh.

(un)Inheritance in C#

this is strange but I really need it. I need to inherit a class without inherit their base class but I don't know how.
I have a base abstract entity class from a framework like this:
public abstract class AbstractEntity
{
public bool Validate(){};
public List<ValidationErrors> erros;
// and so many more properties and methods
}
My custom class inherit this abstract base class:
public class Contact : AbstractEntity
{
public int id
public string name;
public string phone;
}
I'm using this class Contact on a webservice and I need only the custom properties, how can I re-use the class Contact without the inheritance AbstractEntity?
I don't want to duplicate this class. Sorry if this sounds stupid.
EDIT
This is a project already created with a code generator, I can't change the classes structures. For this reason I wanted to instantiate that class without the abstract class.
As I can not change it now and need it urgently, I will duplicate this class without the abstraction and use it.
Sounds like you need an interface.
Extract an interface (IAbstractEntity) from AbstractEntity. Or maybe IContact from Contact- the question isn't very clear about which class has the methods and properties that you want to share. It would looks something like this:
public interface IContact
{
int Id { get; }
string Name { get; }
string Phone { get; }
}
Implement IContact on Contact. Then modify any methods that only use the particular methods/properties in IContact to use an IContact instead of Contact.
And I agree with #Jamie-Penney, it sounds like you should read http://en.wikipedia.org/wiki/Data_transfer_object
Finally, if this is a DTO, you are probably going to find yourself in need of something like AutoMapper
As far as I know you cannot break the inheritance chain. If you want a Contact that doesn't inherit AbstractEntity, you must create a new Contact class that doesn't list AbstractEntity as a parent.
Sorry, that's just how C# is designed.
Try containment.
public class NotAnEntity
{
public Contact { get; set; }
public static implicit operator Contact(NotAnEntity other)
{
return other.Contact;
}
}
While I think that using a simple DTO would probably be the easiest solution, another option would be to implement the IXMLSerializable interface on your Contact class and have it only serialize the properties you care about. Of course, this would affect the XML serialization of the object in other situations as well, not just with the web services.

C# Partial Classes

I currently have a solution with multiple projects that mostly use the same classes. As a result, it appeared to me that it would be a good idea to add a class library containing these classes in the solution instead of repeating the class in each project.
However, one project I have requires a few additional properties to some of the classes that are specific to that project and will not be used anywhere else. As a result, I thought that I should use partial classes to add these properties. So I have done something like this:
In the class library:
namespace MyClassLibrary
{
public partial class Book
{
public string Title { get; set; }
public string AuthorLast { get; set; }
public string AuthorFirst { get; set; }
public string Publisher { get; set; }
public string Edition { get; set; }
public string ISBN10 { get; set; }
public string ISBN13 { get; set; }
}
}
In the project (MyProject):
namespace MyClassLibrary
{
public partial class Book
{
public string AdditionalProperty { get; set; }
}
}
I have referenced MyClassLibrary in MyProject (a C# windows form app), however when I try to use this class in the codebehind for the form I receive the following error:
class MyClassLibrary.Book
Warning: The type
'MyClassLibrary.Book' in 'C:...
(Project)' conflicts with the imported
type 'MyClassLibrary.Book' in 'C:...
(Class Library DLL)'. Using the type
defined in 'C:...(project)'.
Any idea what I am doing wrong or if my whole approach is bad and I should be doing something else?
Partials are not for spanning assemblies. If you need to add to your class for a more specific type of usage, you should create a derived class:
public class MyFoo
{
public string BasicProperty {get;set;}
}
public class MySpecificFoo : MyFoo
{
public string AnotherProperty {get;set;}
}
In your project requiring the more specific type of MyFoo, utilize MySpecificFoo instead. Since it inherits/derives from MyFoo, it will have all of the properties and functionality of MyFoo, with the additional properties as well. This is part of Polymorphism, which is where real power of OOP lies.
In short, you can't use partial classes across projects. All the source must be compiled at the same time, and that's done per project.
Here's a full discussion on SO about this: Should you use a partial class across projects?
For what you're trying to do, you should instead try to use base classes and inheritance. Or even better object composition.
I think this is more along the lines of what you're trying to achieve.
Put all of your common classes into a class library project and compile it to a DLL.
You can then reference that DLL in external projects. Anytime you need to add a property to it for the external project you can then inherit the class and add the property there.
all wrong. You should consider partial methods instead. Look 'em up. They're exactly what you asked for.

Is it possible to have 2 Base class's which already inherit from something inherit or know of a third common class?

I have 2 class's
Class 1.
public class BaseContentPage : System.Web.UI.Page
{
}
Class 2.
public class BaseUserControl : System.Web.UI.UserControl
{
}
And now i want them to be aware of this class.
public class BaseCommon
{
public string Variable1 { get; set; }
public string Variable2 { get; set; }
public string Variable3 { get; set; }
}
How I'm currently doing it is by making the variables of the BaseCommon class static like so
public static string Variable1 { get; set; }
public static string Variable2 { get; set; }
public static string Variable3 { get; set; }
How else can i do this?
Use composition.
Give BaseContentPage and BaseUserControl a private field (which can be exposed as a property if needed) of type BaseCommon (don't make it static).
They can either create BaseCommon or have an instance passed in through the constructor (Dependency Injection).
First off, I don't think you want the BaseCommon properties to be static. The properties are then global across the application so changing them from one instance will change them for all instances.
What you're talking about is multiple inheritence and it isn't supported by c#. You'd be better off changing BaseCommon to be an interface and having BaseContentPage and BaseUserControl implement that interface.
If they are static, does that mean that this third class is a global resource? You could look at Singleton or IoC containers or pass the instance to the other classes when constructed.
You need to give more concrete examples of what this common "base" data that you are adding to two different parts of your object inheritance tree are.
Conceivably, say each instance really just has similar data (an example I'm thinking of is internationalization, say, which is used to customize both a page and a usercontrol according to phrase IDs, etc which are specific in context), then what you can do is have a class I18nSettings which implements II18nSettings. Then in each class, encapsulate an I18nSettings instance and implement II18nSettings and pass them through. Alternatively, you can expose the internal I18nSettings instance. I've even just defined an interface and had each class implement it - it was not worth having a separate class at all.
There are other options to do this kind of thing - it depends on whether the concrete classes you are inheriting from implement a lot more useful things than the things you are adding. It might make more sense to inherit from your concrete class and implement other interfaces so that the class can be used in other places.

Categories