C# Partial Classes - c#

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.

Related

How to hide lower tiers from the upper ones yet make them able to pass data?

I am doing a home project in C#. My project includes EF. It has a database, an EF auto-generated entity class library with all the model classes in it, a repository tier and a presentation tier. I want the presentation tier to be independent from the data tier. I thought I made another one tier that contains the Entity interfaces so in the upper layers I could reference only the interface tier and still be able to pass data, without accidentaly modify the data or to be dependent from the data. However this doesnt work because the model generator class throws an exception that the properties are not mapped. Im confused right now. How could I achieve this? Is there any design pattern I should consider?
Thanks.
Entity classes are generated as partial classes so that you could extend these classes with other members like methods, fields etc. What I would do is I would add another partial class in the Repository project that implements desired interface. This interface would be defined in your interface project. This way you can return interface from repository instead of specific class.
In you repository this is auto generated data model
public partial class EntityClass
{
public int MyProperty { get; set; }
public string String { get; set; }
public bool Boolean { get; set; }
}
Then in the same project you define partial class with the same name. Remember to keep exactly the same namespace here as you have for original auto generated model!
public partial class EntityClass : IEntityClass
{
public int AnotherOne { get; set; }
}
And in your interface project you could add something like this
public interface IEntityClass
{
int MyProperty { get; set; }
string String { get; set; }
bool Boolean { get; set; }
int AnotherOne { get; set; }
}
Remember that this is very cumbersome approach because you have to remember to update your interface whenever you change your data model. Other way around that is commonly used is defining DTOs (Data Transfer Object).
Here someone asked similar question. Please read this.

Is there a built-in or common way to serialize a class definition?

I wonder if there is a standard or at least common way to serialize a class definition in .net? Not an instance of the class (an object) but the actual class definition itself, e.g.:
public class Foo {
[Required]
public string Bar { get; set; }
[Range(1,1000)]
public int Faz { get; set; }
}
var schema = SomeClass.SerializeDefinition(typeof(Foo));
=> schema is a string I can send somewhere that can now recreate the class
Visual Studio can generate WSDLs using wsdl.exe, but I need to do that from code. Unfortunately, Googling mostly yields results on how to serialize objects/instances or how to use external tooling.
I can build something myself using reflection, but before I build my own wheel I'd figured it's worth checking here.

I get InvalidOperationException when I try to use Metadatatype with a viewmodel

I have a model with certain properties. I use a separated class with the MetadataType to define requirements for properties. I also try to use the same metadata class with a viewmodel defining just a subset of properties. This is a simple example code of the situation for clarification:
[MetadataType(typeof(Metadata))]
class ModelA
{
public class Metadata
{
[Required]
public object Property1 { get; set; }
[Required]
public object Property2 { get; set; }
}
public int Property1 { get; set; }
public int Property2 { get; set; }
}
[MetadataType(typeof(ModelA.Metadata))]
class ViewModelA
{
public int Property1 { get; set; }
}
The problem is when the razor engine tries to process the view, it throws the an InvalidOperationException with the following error message:
The associated metadata type for type 'ViewModelA' contains the following unknown properties or fields: Property2. Please make sure that the names of these members match the names of the properties on the main type.
In my understanding the problem here is that the metadata contains properties which the the view model does not. However, this way I don't really understand the advantages of having a metadata class. So my questions are
1) Is there a way to prevent of throwing this exception?
2) If not, what it the best pattern to this situation? (like using a model, a viewmodel, which contains the subset of the properties of the model, defining data annotations by keeping the DRY approach).
MetadataTypeAttribute's are typically used in cases where you want to apply Metadata to auto-generated objects. If you were to apply the metadata to the objects themselves, they would be overwritten when the objects were regenerated.
This is typically done via partial classes. For instance see below. In this case, you create an empty partial class that is the same name as the auto-generated class, it's of course named the same, but you add the MetadataType attribute to it, and you include the nested Metadata class within it.
You do not typically use this with other classes, as other classes would have to have identical (or supersets) of properties.
// Do no edit this class as it is auto generated
public partial class ModelA
{
public int Property1 { get; set; }
public int Property2 { get; set; }
}
// This class can be edited
[MetadataType(typeof(ModelA.Metadata))]
public partial class ModelA
{
public class Metadata
{
[Required]
public object Property1 { get; set; }
[Required]
public object Property2 { get; set; }
}
}
So, to answer your questions:
1) No, you can't prevent the exception, because Metadata has to describe all the properties of it's parent class, and if those properties don't exist, it throws.
2) You would have to create alternate metadata classes. Since this is just as much work as creating a stand-alone view-model, there is no real benefit to using buddy classes for view models that are subsets.
A lot of people get caught up in the DRY concept. The problem is that every software implementation has competing requirements. DRY is often at odds with Single Responsibility Principle.
MetadataTypeAttribute is really more of a hack anyways to deal with the way that the designers generate code. If you're using Code First, then I would strongly discourage using MetadataTypeAttribute.

Compiling Partial Classes with CSharpCodeProvider

I have a code template which builds files in a project's folder, and uses the properties defined in the partial classes to determine which properties still need to be implemented. As an example:
public partial class Thingy : IThingy
{
public Foo Bar { get; set; }
}
public interface IThingy
{
Foo Bar { get; set; }
Baz Biz { get; set; }
}
and the template is supposed to generate:
public partial class Thingy
{
Baz Biz { get; set; }
}
I can guarantee that the template will generate the remaining info to satisfy the expectations of the interface and thus would even be able to generate the class, except the CSharpCodeProvider balks at the notion of only getting half of the interface implemented in the non-generated partial class. Is there a way to tell the provider to ignore that an interface is being implemented at all?
EDIT: I've given this a little more thought, and figured a workaround in the form of actually reading the source first into a string, removing the interface references, and throwing the string of code to CompileAssemblyFromSource instead of CompileAssemblyFromFile, but that feels super kludgy and will more than likely introduce bugs. Thoughts?
You need to modify the source to remove interface implementation declaration, I think.

C# How to resolve circular dependency caused by EditorAttribute usage?

In my project I have two libraries that would currently result in a circular dependency which I am unable to resolve.
One library provides common data structures for the whole solution. This library contains a construct similar to this:
namespace Common {
public class Foo {
//[Editor( typeof( UserEditor ), typeof( UITypeEditor ) )]
public UInt32 OwnerId { get; set; }
}
public class User {
public UInt32 Id { get; set; }
}
}
Now in one of the projects in our solution, we would like to edit Foo instances through a PropertyGrid and the OwnerId property should be edited with a custom editor; this one:
using Common;
namespace Common.Gui {
public class OwnerEditor : UITypeEditor {
public static List<User> Users { get; set; }
}
}
Now, I can't just add an EditorAttribute to Foo.OwnerId because that would create a circular dependency and I would like to keep references to Common.Gui out of Common anyway. I would also like to avoid pulling code out of Common into a new assembly as a lot of other projects reference it.
I found a question regarding adding EditorAttribute at runtime, which sounded like a perfect solution, but I was unable to adept that to my problem.
I think that this is a sign of a flawed design. Do you want the class library containing Foo to be unknowning of the editing GUI? In that case it shouldn't contain the EditorAttribute.
One solution could be to regard the Foo class as your model in a MVVM architecture. Then you can create a wrapping ViewModel in the GUI class library where the EditorAttribute is applied. If you extract an interface IFoo which i placed in your model class library you can use the decorator pattern.
You can reference the editor class by name to create a runtime reference.
public class Foo {
[Editor( "Common.Gui.OwnerEditor, Common", typeof( UITypeEditor ) )]
public UInt32 OwnerId { get; set; }
}

Categories