Accessing value of subclass property without instance - c#

I am currently trying to save and load data for multiple classes to/from disk. I am using JSON serialization to read and write a text file with a custom file extension. This works perfectly fine.
However, instead of duplicating the code in every class I want to use inheritance and only have the save/load code once in an abstract superclass. I want to have a different file extension for each class.
Saving is not a problem, because I have an object, so I can simply use an abstract property, but when I want to load the data I don't, so I can't get the property value without first creating an instance of the type I want to load, which I find stupid.
Also, I can't make abstract static/const properties/fields in C# (for stupid reasons, don't even start), and I am out of good ideas.
//this is fine, although I don't really need the new constraint, but I keep it for consistency with the Load function
public static void Save<T>(string filename, T obj) where T : JsonSerializeable, new() {
if (filename.IsNullOrWhiteSpace()) filename = $"{DEFAULT_FILENAME}";
string path = Path.ChangeExtension($"{DIRECTORY_NAME}/{filename}", obj.fileExtension);
path = Path.ChangeExtension(path, obj.fileExtension);
if (!Directory.Exists(DIRECTORY_NAME)) Directory.CreateDirectory(DIRECTORY_NAME);
File.WriteAllText(path, JsonConvert.SerializeObject(obj, Formatting.None));
}
//this works, but I hate that I need to create an instance that has no other use than getting the property value
public static bool Load<T>(string filename, out T obj) where T : JsonSerializeable, new() {
if (filename.IsNullOrWhiteSpace() || !Directory.Exists(DIRECTORY_NAME)) {
obj = default;
return false;
}
string fileExtension = new T().fileExtension; //TODO -.-
string path = Path.ChangeExtension($"{DIRECTORY_NAME}/{filename}", fileExtension);
if (!File.Exists(path)) {
obj = default;
return false;
}
obj = JsonConvert.DeserializeObject<T>(File.ReadAllText(path));
return true;
}
Alternatively, I could have public save/load methods in the subclasses, with the desired interface (i.e. without the extension) and have the superclass methods protected and there pass the extension as parameter. However, I still don't really like that. It is acceptable, and my current implementation (because creating a useless object doesn't fly), but is there a good way to do it with only the superclass functions? (and no, I don't want to use the class name as the file extension)
Note: As of now this is more of an academic question, since I have a working implementation, but this was only the latest instance of that same problem popping up in my programming over and over again, and I always find some kind of workaround. I would love to finally have a good solution.

One way to do this would be to create an abstract class with a static member for the Extension property, and then hide that property in the child class implementations:
public abstract class FileType
{
public static string Extension { get; } = "default";
}
public class PDFFile : FileType
{
public static new string Extension { get; } = "pdf";
}
public class TextFile : FileType
{
public static new string Extension { get; } = "txt";
}

Related

Class behavior based on given data

I am receiving an IFormFile from a controller.
What I want to do next is to process it and get its content. I expect to get .docx, .txt or .pdf file and I want a single class to process any of these files based on extension given. I created and made my class to do it like that:
{
public static class DocumentProcessor // Should it be like this?
{
public static string GetContent(IFormFile file)
{
var result = new StringBuilder();
switch (Path.GetExtension(file.FileName))
{
case ".txt":
{
using(var reader = new StreamReader(file.OpenReadStream()))
{
while (reader.Peek() >= 0)
result.AppendLine(reader.ReadLine());
}
break;
}
}
return result.ToString();
}
}
}
Anyway, I feel like it is an extremely bad solution just because it is static. I could use the strategy pattern, but how do I define what strategy context has to use?
Should I create another class that
returns a Strategy object depending on IFormFile object extension. But I feel it is also a bad solution
I would like to know what is the best way to solve this problem
Create a new interface
interface IDocumentParser {
string GetContent(IFormFile file);
}
Implement that interface once per parser extension, e.g.:
class TextFileParser : IDocumentParser {
public string GetContent(IFormFile file) {
//your implementation code here
}
}
Then implement a factory:
class ParserFactory {
public static IDocumentParser GetParserForFilename(string filename) {
/*
This is the simple way. A more complex yet elegant way would be for all parsers to include a property exposing the filetypes it supports, and they are loaded through reflection or dependency injection.
*/
switch (Path.GetExtension(fileName))
{
case ".txt":
{
return new TextFileParser();
}
// add additional parsers here
}
return null;
}
}
And use:
IDocumentParser parser = ParserFactory.GetParserForFilename(file.FileName);
string content = parser.GetContent(file);
This is known as "Inversion of Control".

How to dynamically decide which static class to use

We have a large class that contains a bunch of css selectors stored as static strings. Example:
public class Constants
}
public static string Selector1 = "#someID";
public static string Selector2 = ".some.classes a";
// and so on...
}
We now need to test a different version of our web app which requires a few different selectors. So we need to find a clean scalable way to override these selectors based on some configuration.
My solution to the problem is this: I'm trying to create a BaseConstants class which will have the current set of selectors. Then I create another class called UpdatedConstants which will subclass the BaseConstants class. This class will then contian all the selectors and just override the ones that need changing with the new keyword. Example:
public class UpdatedConstants : BaseConstants
{
// Overrides the base class's Selector1 string
public new static string Selector1 = "#someOtherID";
}
This works well for overriding the strings however I'm stumped as to how the project will decide which static class to use when it is compiled. All our existing code uses the Constants class like this:
var element = driver.GetElement(Constants.SomeSelector);
Is there a way to dynamically decide which class is the final Constants class? Perhaps by some meta-programming magic?
Let me know if anyone has questions or needs a better explanation of the problem. Thanks
Make your constants classes non-static and use a singleton. This also lets you use virtual properties, since you want to use a base Constants class.
public static class Constants
{
static Constants()
{
#if FOO
Current = new ConstantsFoo();
#elif BAR
Current = new ConstantsBar();
#endif
}
public static ConstantsBase Current { get; private set; }
}
//...snip
var element = driver.GetElement(Constants.Current.SomeSelector);
If you don't want to change all occurences Constants.SomeSelector, the only way to have different behavoirs is using pre-processor directives in the Constants class:
public class Constants
}
#if OLD
public static string Selector1 = "#someID";
#elif NEW
public static string Selector1 = "#someNewID";
#endif
public static string Selector2 = ".some.classes a";
// and so on...
}
Else you can use the approach from Ed Plunketts answer.
Okay, probably not what you're looking for, but... You might want to consider not doing it like this.
Put it this way - if you travel down the road, what will your code look like in 5 years? You'll have a base class that contains your original settings, a subclass for how they were modified the first time (when you asked this question), a subclass inheriting from that subclass on how they were modified the next time, and so on. I could easily imagine 10 subclasses in a giant chain - and if you wanted to trace the current value for any setting, you'd have to travel up that chain until you found where it was most recently set/overriden. It sounds like a maintenance nightmare, to be honest.
If I were in your shoes, this is what the new code would look like:
public static class Constants
{
public static string Selector1 { get { return ReadFromSettings("Selector1"); } }
public static string Selector2 { get { return ReadFromSettings("Selector2"); } }
//etc
// then, code for ReadFromSettings()
}
... and then migrate those settings into an actual settings file. Nobody needs to change any code on the calling end (they still reference Constants.Selector1) - except, instead of having this all hard-coded in a series of derived classes, you just have a file with your values.

How to create a "pointer-like" class, easily exposing functions of member?

What I am trying to do is find the most elegant way to create a "pointer-like" class for a specific object/class type that I have in a project.
What I mean is a little confusing without an example. Take this really simple class:
public class MyClass
{
private string _name;
public string GetName() { return _name; }
public void SetName(string name) { _name = name; }
}
I want to create a second class which is like a pointer to it like this:
public class MyClassPtr
{
private MyClass _obj;
public bool IsValid = false;
public MyClassPtr(MyClass obj) { _obj = obj; IsValid = true; }
public void InvalidatePtr()
{
IsValid = false;
obj = null;
}
// SOME MAGIC HERE?
}
The challenge: The key is that I want to elegantly have MyClassPtr provide an interface to all of the public methods/members in MyClass without writing wrappers and/or accessors around each method/member.
I know that I could do this:
public class MyClassPtr
{
public string GetName() { return _obj.GetName(); }
...
}
But that's what I want to avoid. Is there some fundamental abstraction that I don't know of that I can apply to MyClassPtr to allow it to easily re-expose the methods/members in MyClass directed through _obj? I do NOT want MyClassPtr to inherit MyClass. Should MyClassPtr be a type instead, and some trick with accessors to expose the methods/members of MyClass?
Edit: More context on why I am looking for such a design through an example. Here is the overall goal. Imagine a platform that parses through data about people and when it finds information about a person, it creates an instance of Person with that information. You could get a handle to that person like:
Person person1 = platform.GetPerson(based_on_data);
Now, imagine the platform had two instances of Person that it thought were different people, but all of a sudden information came in that strongly suggested those two instances actually refer to the same person. So, the platform wants to merge the instances together in to a new object, let's call it personX.
Now, floating around in the platform someone had a copy of one of those two instances that got merged, which was person1. What I want to do is on-the-fly replace person1 with personX. Literally, I want person1==personX to be true, NOT just that they are two different objects with the same data. This is important since the platform could make a change to personX and unless the two objects are literally equal, a change to personX would not be automatically reflected in person1.
Since I can't on-the-fly replace person1 with personX I had that idea that I wouldn't give direct access to Person, instead I would give access to PersonPtr which the platform (on-the-fly) can change what Person it is pointing to. This would insurance that once person1ptr gets updated to point to personX, if a change is made in personX it will be seen in person1ptr
You could of course use something like
public class MyClassWrapper
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public void Invoke(Action<MyClass> action)
{
action(_obj);
}
public U Invoke<U>(Func<MyClass, U> func)
{
return func(_obj);
}
public void ChangeTo(MyClass obj)
{
_obj = obj;
}
}
Given your class looks like
public class MyClass
{
public string Name { get; set; }
}
Example:
var person1 = new MyClass { Name = "Instance1" };
var person2 = new MyClass { Name = "Instance2" };
var wrapper = new MyClassWrapper(person1);
wrapper.Invoke(x => x.Name += "original");
var x = wrapper.Invoke(x => x.Name); // Instance1original
wrapper.ChangeTo(person2);
var y = wrapper.Invoke(x => x.Name); // Instance2
but it has a major drawback: you can't access members directly, so you can't bind the data (to a DataTable or a Control).
It would be better to implement all members of your class also in your wrapper class. If you're afraid changes in your class will be forgotten to be implemented in your wrapper, just use an interface:
public interface IMyClass
{
string Name { get; set; }
}
public class MyClass : IMyClass
{
public string Name { get; set; }
}
public class MyClassWrapper: IMyClass
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public string Name
{
get { return _obj.Name; }
set { _obj.Name = value; }
}
}
Note that regardless which approach you use, you'll have to always keep a reference to the wrapper instance to actually change the underlying instance (using something like static aside).
Also, changing the underlying instance of such a wrapper without telling the component using it that it changed don't seem to be a good idea. Maybe your system is simple enough to get away with a wrapper; that's something you have to decide for yourself.
Maybe your wrapper should simply have an Invalid flag (and/or use an event to signal a change of the underlying object.). Once the underlying object is merged, it is set to true and each member access should throw an exception. This would force the component using the wrapper to deliberately react to changes and to reload the data from your service.
All in all, I think using such a wrapper will just clutter up your code and be error prone (just imagine adding multithreading to the mix). Think twice if you really need this wrapper.
Why not just simply ask your service for a new instance of your class everytime you use it (the service can simply use a cache)? Sure, you can't prevent that someone somewhere keeps a reference; but at least you'll keep your sanity.

How to make an enum variable based on classes in project

I'm writing a DLL that will expose a method like this:
public static void Convert(string inputFile, string outputFile, FileType fileType)
At the moment, FileType is an enum that is exposed like this:
public enum FileType
{
ConvertClassOne,
ConvertClassTwo,
ConvertClassThree
}
This will represent each class that can convert a given type of file. I'll have several different classes based on an interface, each of which can process a particular type of file.
Instead of having an enum like I have above, where I have to change it manually each time I add a class so that the calling program can tell me which file type they're giving me, I'd like to expose an enum that automatically changes itself based on the classes in my project that have a given attribute.
So if I add a class with a given attribute:
[SomeAttribute]
public class NewClassAdded()
{
}
the FileType enum will pick this up and the calling program will be able to see
FileType.NewClassAdded
without me having to change anything else by hand. I'm pretty sure that Reflection will allow me to write a method that returns the name of each class with the given attribute, but I'm not sure exactly how, nor do I know how I would then expose these names as an enum.
Thanks,
Andrew
This may not be the answer you are looking for, but have you considered using generics? It would solve the problem that you can add new functionality. You could use an interface that represents your enum. For each enum value, there would be a class that implements that interface. Whenever you want to add a new option, just add a new class implementing the interface. You can put additional functionality in these classes, or you could just use them as substitutes for enum values (variant 1 and 2 in the code below). Example:
class Program
{
static void Main(string[] args)
{
Converter.Convert("input", "output", new FormatA());
Converter.Convert("input", "output", new FormatB());
}
}
class Converter
{
public static void Convert<T>(string inputFile, string outputFile, T formatter) where T : IConvertFormat
{
// First variant: Keep the functionality in the formatter object
formatter.DoSomething(inputFile, outputFile);
// Second variant: check for the actual type
if (formatter is FormatA)
{
// ... do format A
}
else if (formatter is FormatB)
{
// ... do format B
}
}
}
interface IConvertFormat
{
// Method not required for variant 2
void DoSomething(string inputFile, string outputFile);
}
class FormatA : IConvertFormat
{
public void DoSomething(string inputFile, string outputFile)
{
// .. do it like Format A (not required for variant 2)
}
}
class FormatB : IConvertFormat
{
public void DoSomething(string inputFile, string outputFile)
{
// do it like Format B (not required for variant 2)
}
}
PS. I think that is basically what #Jauch is proposing.
Based on the discussions, I'll give you the following idea, #Starfleet.
First, create an interface with a "conversion" function and a "description" property.
interface IFileConversion
{
bool Convert (string inputFile, string outputFile);
string Description { get; }
}
Put this interfaces on a dll, and any class that wants to implement it can reference it.
Then, you can implement this interface on any "FileType" class you have.
In your library you can create a function to return all classes that implement IFileConversion (through reflection is pretty easy).
Something like:
static class Info
{
public static List<IFileConversion> AvailableConversions ()
{
//Code to retrieve the available classes that implement IFileConversion
}
}
This way, if you want to "enumerate" the available classes in your library (and show them to a user through some kind of visual interface), just call Info.AvailableConversions.
And them show to the user the available conversions using the "description" property.
But, if this is not the case and what you want is simply to other developers to know what are the available conversion classes, the better is through documentation. If you use the "///" you can give information and description that usually shows up on code completion in most UIDev. In this case, you can create a particular namespace, like:
namespace FileConversion
{
//Put all conversion classes under this namespace
}
And it's easy to see the available just typing "FileConversion." and iterating through the list that will appear (with the extra information you gave).
The advantage of using the IFileConversion interface is that your partners (other developers) do not have to worry about known anything about the class. They just chose the one they want (through the description or documentation) and call the Conversion routine.
In any case those two solutions are better and much more descriptive than just the enumeration descriptor.

How to deal with a sealed class when I wanted to inherit and add properties

In a recent question on Stack Overflow, I asked how I might parse through a file name to extra meta info about a file.
After I worked through that problem, I decided that I might want to create new type of object to hold the meta data and the original file. I thought I might do something like this:
class BackupFileInfo : FileInfo, IEquatable<BackupFileInfo>
{
//Properties and Methods here
}
The idea would be that I would retain the original FileInfo object while adding meta information in the properties of the object that implements FileInfo, such as IsMainBackup.
However, FileInfo is sealed, which means other classes cannot inherit from it.
Instead, I ended up with the following:
class BackupFileInfo : IEquatable<BackupFileInfo>
{
public bool IsMainBackup { get; set; }
public int ImageNumber { get; set; }
public int IncrementNumber { get; set; }
public FileInfo FileInfo { get; set; }
//public BackupFileInfo() //constructor here
public bool Equals(BackupFileInfo other)
{
return (this.FileInfo.Name == other.FileInfo.Name
&& this.FileInfo.Length == other.FileInfo.Length);
}
}
I'm not terribly excited about this solution because instead of being able to use BackupFileInfo.Length, I'm going to have to use BackupFileInfo.FileInfo.Length. Perhaps this is the best practice already, but something doesn't feel right.
Is there a better way to deal with this problem?
This is one of the classic composition instead of inheritance examples and you went in the right direction.
To solve your property problem just create a property called Length that delegates to the encapsulated FileInfo object.
You could add an implicit operator to your class.
Eg:
class BackupFileInfo .... {
/* your exiting code */
public static implicit operator FileInfo( BackupFileInfo self ){
return self.FileInfo;
}
}
You could then treat your BackupFileInfo object like a FileInfo object like so
BackupFileInfo bf = new BackupFileInfo();
...
int mylen = ((FileInfo)bf).Length;
You could just expose the properties on FileInfo you care about. Something like this:
public long Length { get { return FileInfo.Length; } }
This obviously becomes less practical if you want to delegate a lot of properties to FileInfo.
Pass-thru?
class BackupFileInfo : IEquatable<BackupFileInfo>
{
public long Length {get {return FileInfo.Length;}}
//.... [snip]
}
Also, a prop called FileInfo is asking for trouble... it may need disambiguation against the FileInfo class in a few places.
This doesn't really solve your larger problem, but of course you can just make the properties you want to use act as proxies to the real properties underneath. E.g.
public long Length
{
get {return FileInfo.Length;}
}
(With approriate null-checking of course.)
You can easily wrap the file info properties in your own properties if you like.
public long Length
{
get
{
return this.FileInfo.Length;
}
}

Categories

Resources