I have to use these two different class files across my application. How do I inherit those two class files in another class file?
This class file to writes an information log
Public class Log
{
Public void createLog()
{
}
}
This class file gets connection string
public class DataConnector
{
public void Connection()
{
}
}
I want to Inherit from those two classes in this class:
Public class FileOperation
{
public void FileWiter
{
}
}
Are there any different ways to access the class files across my project?
What I have tried:
Public class FileOperation
{
Log oLog=new Log();
DataConnector oDataconn=new DataConnector();
public void FileWiter
{
oLog.createLog();
}
}
Yes, I can use that method, but I'm looking for any other best ways to do this?
Basically, there is nothing wrong with your approach. There is even an OOP Design Principle called composition over inheritance, which calls for this way of doing it.
Think about DataConnector, does you FileWriter really specialize some kind of DataConnector?
What I would recommend though would be hiding your dependencies behind interfaces and injecting them via the constructor of FileOperation like so:
public class FileOperation
{
ILog log;
IDataConnector dataConnector;
public FileOperation(ILog log, IDataConnector dataConnector)
{
this.log = log;
this.dataConnector = dataConncetor;
}
public void FileWiter
{
this.log.createLog();
}
}
This way you could easily swap one or both of those dependecies by simply passing another object which implements the right interface. For example, you could create a MongoDbDataConnector which implements IDataConnector and pass this one instead of a MsSqlDataConnector or a PostgreSqlDataConnector.
There is no reason why your FileOperation should inherit from either Log nor DataConnector. Your FileOperation uses the Log and the DataConnector, but it shouldn't change how you Log or how you connect to your Data.
You could however prepare for the future, and create an interface for your Log class and for your DataConnector, so that at any time in the future you could easily swap those classes for another implementation, like so:
public interface ILogger
{
void Log(string message);
}
public interface IDataConnector<T>
{
IList<T> ReadList(Predicate<T> matches);
T ReadItem(Predicate<T> match);
}
and implement your classes for these interface.
In your FileOperation class, you can then set these over interfaces, and potentially later fill them using dependency injection, like so:
public class FileOperation
{
public ILogger Log { get; set; }
public IDataConnector DataConnector { get; set; }
public FileOperation()
: this(new Logger(), new DataConnector<string>())
{
}
public FileOperation(ILogger log, IDataConnector dataConnector) {
Log = log;
DataConnector = dataConnector;
}
}
Related
I've made a class with T. It looks like this.
public interface ISendLogic<T> where T : NarcoticsResult
{
ChangeType Change_New();
ChangeType Change_Cancel();
PurchaseType Purchase_New();
PurchaseType Purchase_Cancel();
}
public class SendLogic<T> : ISendLogic<T> where T : NarcoticsResult
{
private eReportType _type;
private bool Send_Change()
{
// Send to server by xml file
}
private bool Send_Purchase()
{
// Send to server by xml file
}
public ChangeType Change_New()
{
_type = change_new;
Send_Change();
}
public ChangeType Change_Cancel()
{
_type = change_cancel;
Send_Change();
}
public PurchaseType Purchase_New()
{
_type = purchase_new;
Send_Purchase();
}
public PurchaseType Purchase_Cancel()
{
_type = purchase_cancel;
Send_Purchase();
}
}
There are two types, ChangeType and PurchaseType
and these are inherited from NarcoticsResult.
I thought the person who want to use this class would use it like this.
// this class can only be used when someone wants to use change function
var logic = SendLogic<ChangeType >();
logic.Change_New();
logic.Change_Cancel();
Here is a question.
I want to force this class to be used only as I thought.
I mean, I want to prevent it to be used like this.
var logic = SendLogic<ChangeType>();
logic.Change_New(); // OK
logic.Purchase_New(); // You should make this class like SendLogic<PurchaseType>()
I thought I add some code which check type of T in every function.
How do you think the way I thought. I think there are better way to fix it
Please tell me a better way
thank you.
Personally, I don't think you need a generic class in this case. What you need is either an abstract base class or an interface. I personally love the interface approach as below:
public interface ISendLogic {
void New();
void Cancel();
}
So now you've got a contract that will force the consumer of your code to use New or Cancel methods only.
The next step you can implement that send logic interface for your specific implementation:
public class ChangeSendLogic : ISendLogic {
private eReportType _type;
public ChangeSendLogic(
/*you can put the necessary parameters in the constructor
and keep it as private fields in the object*/
)
{
}
private bool Send_Change()
{
// Send to server by xml file
}
public void New()
{
_type = change_new;
Send_Change();
}
public void Cancel()
{
_type = change_cancel;
Send_Change();
}
}
public class PurchaseSendLogic : ISendLogic {
private eReportType _type;
public PurchaseSendLogic(
/*you can put the necessary parameters in the constructor
and keep it as private fields in the object*/
)
{
}
private bool Send_Purchase()
{
// Send to server by xml file
}
public void New()
{
_type = change_new;
Send_Purchase();
}
public void Cancel()
{
_type = change_cancel;
Send_Purchase();
}
}
From here you can see those two classes handle the implementation for each type nicely. You can think this is as an implementation of single responsibility principle. So if you have one more type, you can just add one more implementation of this interface rather than updating the existing classes.
If you want to hide the creation of those objects, in the next part you can introduce a kind of factory or selector as below:
public enum SendLogicType {
Change,
Purchase
}
public static SendLogicSelector {
public static ISendLogic GetSendLogic(SendLogicType type)
{
switch(type)
{
case SendLogicType.Change:
return new ChangeSendLogic();
case SendLogicType.Purchase:
return new PurchaseSendLogic();
}
}
}
This is how the code will be consumed:
ISendLogic sendLogic = SendLogicSelector.GetSendLogic(SendLogicType.Change);
sendLogic.New(); // change new logic executed
sendLogic.Cancel(); // change cancel logic executed
sendLogic = SendLogicSelector.GetSendLogic(SendLogicType.Purchase);
sendLogic.New(); // purchase new logic executed
sendLogic.Cancel(); // purchase cancel logic executed
Hopefully, you can get the idea of my approach. Good luck! :)
Thank you for your comment
I divided it into two parts like below
public class ChangeSendLogic : SendLogic<ChangeType>, IChangeLogic
public class PurchaseSendLogic : SendLogic<PurchaseType>, IPurchaseLogic
And I also divided interface too
public interface IChangeLogic
{
ChangeType Change_New();
ChangeType Change_Cancel();
}
public interface IPurchaseLogic
{
PurchaseType Purchase_New();
PurchaseType Purchase_Cancel();
}
And I made SendLogic<T> class to abstract class.
This is because I want to make the person who wants to use this class to use a class that inherits from this class without directly accessing it.
Thank you for your comment. I got a good idea.
I am using log4net, and want to simplify the usage. Right now, in every class I use logging (which is almost all all classes), I have to write:
public class MyClass
{
public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
try
{
// do something
}
catch(Exception ex)
{
log.Error("Problem doing something", ex);
}
}
What I would really like to do is to put the first declaration in another class, which I could inherit wherever I need logging:
public class MyClass : Logging
{
try
{
// do something
}
catch(Exception ex)
{
log.Error("Problem doing something", ex);
}
}
public class Logging
{
public static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
}
But, if I do this, the problem is that
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType
...ends up picking up the class name Logging, which is no good for the log. How do I get it to pick up the class name of the class where the inherited logging class is used?
Thanks!
If you inherit all your classes from Logging class then you won't be able to inherit classes from any other classes and create inheritance structure because C# does not support multiple inheritance. You really need to use composition not inheritance.
You can simplify calls to your logger by creating static helper class:
public static class LoggerHelper
{
public static void WriteError(string message,Exception ex, Type type)
{
var log = log4net.LogManager.GetLogger(type);
log.Error(message, ex);
}
}
And then in you classes you will call it like this:
public class MyClass
{
try
{
// do something
}
catch(Exception ex)
{
LoggerHelper.WriteError("Problem doing something", ex, this.GetType());
}
}
Declare your base class like so:
public abstract class Logging
{
public readonly log4net.ILog log = log4net.LogManager.GetLogger(this.GetType());
}
this.GetType() will always return the concrete type.
So you're gonna make all your classes inherit from Logging?
Inheritance is not meant for code reuse, it's meant to represent a "is a kind of" relationship between two domain entities. Don't abuse it.
What you need is composition.
public class MyClass
{
private static readonly ILog log = LogManager.GetLogger(typeof(MyClass));
}
MyClass has a logger, it is not a logger.
I've got something like this:
// This gets implemented by plugin authors to get callbacks about various things.
public interface ExternalPlugin
{
// This gets called by the main application to tell the plugin some data
// is available or similar.
void DoStuff(SomeDataBlob blob);
}
// Data blob for v1 of API
public class SomeDataBlob
{
internal SomeDataBlob(string prop) { Prop = prop; }
// Some piece of data that V1 plugins need
public string Prop { get; private set; }
}
// FUTURE!
// Data blob API v2 of API
public class SomeDataBlobV2 : SomeDataBlob
{
// Can be passed to clients expecting SomeDataBlob no problem.
internal SomeDataBlobV2(string prop, string prop2) :base(prop) { Prop2 = prop2; }
// Some piece of data that V2 plugins need. V2 plugins can cast to this from
// SomeDataBlob, but still can load successfully into older versions that support
// only V1 of the API
public string Prop2 { get; private set; }
}
I have to make SomeDataBlob public so that it can be used as a member of the public interface method ExternalPlugin.DoStuff. However, I would not like to allow clients to inherit from that class and thus be susceptible to the brittle base class problem. (All derivatives of that class should be kept in the same assembly)
Marking the class sealed goes too far because I believe removing sealed is a breaking API change; and even if that isn't, once I ship SomeDataBlobV2 clients could still do the wrong thing and inherit from SomeDataBlob directly.
Is there a way to enforce this kind of pattern?
Make the class internal, and expose an interface instead. Then use the factory pattern to create the correct implementation.
public interface ISomeDataBlob
{
}
internal class SomeDataBlob : ISomeDataBlob
{
}
public class BlobApiFactory
{
ISomeDataBlob Create();
}
You hide the implementation, but still give the user access to everything. You even make unit tests easier for your users ;)
Edit (answer to a comment from the OP)
What I effectively want is some method taking some parameters. I want to be able to add parameters that the main application can provide in a future version if the API without breaking clients. But I don't want clients to be able to create instances of the "parameters" class/interface or otherwise interact with it beyond receiving an instance of it as a parameter
Instead of hiding the APIs you can make sure that all object passed to your library originates from your assembly:
public class YourCoolService
{
public void DoSomething(ISomeDataBlob blob)
{
if (blob.GetType().Assembly != Assembly.GetExecutingAssembly())
throw new InvalidOperationException("We only support our own types");
}
}
Edit2
Just noticed that #RQDQ already provided that solution (didn't notice when answering your comment). If that's the solution you want, accept his answer instead.
/// <summary>
/// This is a dummy constructor - it is just here to prevent classes in other assemblies
/// from being derived from this class.
/// See http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2971840&SiteID=1
/// </summary>
internal MhlAdminLayer() { }
The idea is to have a constructor with no parameters internal. Then the class can't be derived from.
Edit: Sorry, the link in the comment doesn't work any more.
Edit 2:
http://msdn.microsoft.com/en-us/library/vstudio/ms173115.aspx
"You can prevent a class from being instantiated by making the constructor private ... "
If you are hell bent on not using sealed AND still using classes, you can enforce this at runtime. In otherwords, at your API boundary, inspect the classes involved and make sure they come from your assembly.
A simple example:
public void Bar(Foo foo)
{
if (foo.GetType().Assembly != this.GetType().Assembly)
throw new InvalidOperationException("It's not one of mine!");
}
public class Foo
{
}
As far as I know, interfaces are the way to do this. It would be an API breaking change, but it would mean you could do what you want.
public interface ExternalPlugin
{
void DoStuff(ISomeDataBlob blob);
}
// Interfaces:
public interface IDataBlob
{
string Prop { get; }
}
public interface IDataBlobV2 : IDataBlob
{
string Prop2 { get; }
}
// Data blob for v1 of API
internal class SomeDataBlob : IDataBlob
{
internal SomeDataBlob(string prop) { Prop = prop; }
public string Prop { get; private set; }
}
// FUTURE!
// Data blob API v2 of API
public class SomeDataBlobV2 : SomeDataBlob, IDataBlobV2
{
// Can be passed to clients expecting SomeDataBlob no problem.
internal SomeDataBlobV2(string prop, string prop2) : base(prop) { Prop2 = prop2; }
public string Prop2 { get; private set; }
}
And then to make the objects use the factory pattern, e.g.
public static class DataBlobFactory
{
public IDataBlob GetDataBlob(string prop)
{
return new SomeDataBlob(prop);
}
// so on.
}
What I would do is make some sort of factory class that exposes an interface that would pass an instance of whatever version for the specific API your client is using, and hide the implementation with an internal class
You can also use constraints to make it little easier to use, then the client can just put the Type of object they are looking for
public interface IBlobV1 { /*public stuff for V1 here*/ }
internal class BlobV1: IBlobV1 {/*v1 implementation*/ }
public interface IBlobV2 : IBlobV1 {/*public interface for V2 here*/ }
internal class BlobV2:BlobV1,IBlobV2 {/*v2 implementation*/}
public sealed BlobFactory
{
public IBlobV1 CreateVersion1Blob(){/* implementation */}
public IBlobV2 CreateVersion2Blob(){/* implementation */}
public T CreateBlob<T>()
where T: IBlobV1
{ /* implementation */}
}
SomeDataBlob can not be inherited because its only constructor is internal. If you try to implement a derived class in a client application:
class SomeDataBlobClient : SomeDataBlob
{
SomeDataBlobClient():base("TEST")
{
}
}
You will get the following error:
The type 'ClassLibrary1.SomeDataBlob' has no constructors defined
It seems that you solved your own problem.
I am planning to solve a particular problem by using abstract factory pattern. I was successful in implementing factory pattern but not able to extend factory pattern to Abstract factory
I have two different places where exception details can be stored
File system
Database
I have used factory pattern to abstract away object creation details from client
Interface
public interface ILogException
{
void LogException();
}
FileSystemLogger
public class FileExceptionLogger : ILogException
{
public void LogException()
{
Console.WriteLine("File Exception Logger");
}
}
DBSystemLogger
public class DBExceptionLogger : ILogException
{
public void LogException()
{
Console.WriteLine("DB Exception Logger");
}
}
Factory Implementation
public class ExceptionFactory
{
const int i = 1;
public static ILogException GetFactory()
{
if (i == 1)
{
return new FileExceptionLogger();
}
else if (i == 2)
{
return new DBExceptionLogger();
}
else
{
return new ServiceExcetionLogger();
}
}
}
I know this is not the best of implementation but i plan to change it.
Now FileSystemLogger and DatabaseLogger are in itself a factory, I want to group following implementation under FileSystemLogger and DatabaseLogger so that the client can have FileSystemLoggerFactory and DatabaseLoggerFactory
FileSystemLogger
FlatFileSystemLogger
XMLFileSystemLogger
DatabaseLogger
SQLSERVERLogger
OracleLogger
How should i proceed with defining FileSystemLoggerFactory and DatabaseLoggerFactory?
If you want, you could make the factory method a generic one:
public static ILogException GetFactory<T>() where T : ILogException
{
return (ILogException)Activator.CreateInstance<T>();
}
Call it like:
ILogException logger = ExceptionFactory.GetFactory<FileExceptionLogger>();
You also might want to take a look at a dependency injection library like NInject, Unity, etc. These can simplify this kind of problem, allowing you to centralize the logic for which interfaces get bound to which implementations. (Ie, you can bind an implementation in the application or request scope.)
class LogUtil<T> : ILogUtility
{
log4net.ILog log;
public LogUtil()
{
log = log4net.LogManager.GetLogger(typeof(T).FullName);
}
public void Log(LogType logtype, string message)
{
Console.WriteLine("logging coming from class {0} - message {1} " , typeof(T).FullName, message);
}
}
public class Logger
{
ILogUtility _logutility;
public Logger(ILogUtility logutility)
{
_logutility = logutility;
}
public void Log(LogType logtype, string message)
{
_logutility.Log(logtype, message);
}
}
I need to have the functionality to be flexible and have the ability to remove the LogUtil class in the future and use some thing else.
So I write LoggerUtility wrapper class as follows:
class LoggerUtility<T>
{
Logger logger;
public LoggerUtility()
{
LogUtil<T> logutil = new LogUtil<T>();
logger = new Logger(logutil);
}
public void Log(LogType logtype, string message)
{
logger.Log(logtype, message);
}
}
My client code as follows:
public class TestCode
{
public void test()
{
new LoggerUtility<TestCode>().Log(LogType.Info, "hello world");
}
}
To get loose coupling from LogUtil, I end up writing 2 wrapper classes Logger and LoggerUtility. So in the future, if I have to add another method
in the ILogUtility, I would have to add that method to Logger class and then LoggerUtility.
What is the best way to write LoggerUtility so that I could write the client code as follows:
new LoggerUtility<TestCode>().Log(LogType.Info, "hello world");
Please let me know.
Thanks
It looks like you're adding a level of abstraction where there really doesn't need to be one.
If we start with your end result, LoggerUtility just needs to have an interface that it can use to log things based on the LogType parameter.
Your Logger class, as its currently written, is just a thin wrapper around the ILogUtility interface. So why bother adding that layer? Why can't the Logger class use an ILogUtility instance directly? You could even go one step further and define your interface as ILogUtility<T> and know that when you create a LoggerUtility<Foo> that the instance of the logger it will use will be based on the Foo class.
But honestly, I think you may just be reinventing the wheel here. Take a look at Common Logging for .NET. It will probably ease what you're trying to do and make more sense in the long run.
You don't need a second wrapper, you need either a factory or to use a dependency injection framework to construct an appropriate wrapper around log4net.
Using Ninject, and modifying your interface, you can do
kernel.Bind(typeof(ILogUtility<>)).To(typeof(Log4NetUtil<>);
and instantiate it as
var logger = kernel.Get<ILogUtility<MyClass>>();
where the logger interface/class are:
public interface ILogUtility<T> where T : class
{
void Log(LogType logtype, string message);
}
public class Log4NetUtil<T> : ILogUtility<T> where T : class
{
log4net.ILog log;
public LogUtil()
{
log = log4net.LogManager.GetLogger(typeof(T).FullName);
}
public void Log(LogType logtype, string message)
{
Console.WriteLine("logging coming from class {0} - message {1} " , typeof(T).FullName, message);
}
}