Reputation: 7987
I have the following interfaces defined:
public interface IAudit {
DateTime DateCreated { get; set; }
}
public interface IAuditable {
IAudit Audit { get; set; }
}
The IAuditable
interface says which classes I will have an Audit
for. The IAudit
interface is the actual Audit
for that class. For example say I have the following implementations:
public class User : IAuditable {
public string UserName { get; set; }
public UserAudit Audit { get; set; }
}
public class UserAudit : IAudit {
public string UserName { get; set; }
public DateTime DateCreated { get; set; }
public UserAdit(User user) {
UserName = user.UserName;
}
}
Now given an object which is IAuditable
(User
from above), I'd like to be able to create an intance of IAudit
(UserAdit
from above) by feeding in the IAuditable
object into the constructor. Ideally i'd have something like:
if (myObject is IAuditable) {
var audit = new IAudit(myObject) { DateCreated = DateTime.UtcNow }; // This would create a UserAudit using the above example
}
However I have a bunch of problems:
IAudit
applies to which IAuditable
IAudit
interface must have a constructor which takes an IAuditable
I'm sure this is a design pattern many have had before but I can't get my head around it. I'd really appreciate if someone could show me how this can be achieved.
Upvotes: 26
Views: 115406
Reputation: 64943
One way would be using generics.
Once you've a T type which implements I interface and has a public, parameterless constructor, you can create an instance of T:
public void Create<T>() where T : IAudit, new()
{
T instance = new T();
// TODO: Your logic here to use T instance of IAudit
}
I don't know your code architecture or goal, but you can create a factory method like one above to create instances of IAudit objects.
Upvotes: 6
Reputation: 1361
You can create a static Interface variable outside of the scope and then use it in the code.
static IRequestValidator ir;
static void Main(string[] args)...
Upvotes: 0
Reputation: 53
If you are in need to create Instance for an Interface,You can create a public class named FactoryClass() which contains all the Interfaces method. you can use the following code:
public class FactoryClass //FactoryClass with Interface named "IINterface2"
{
public IInterface2 sample_display() //sample_display() is a instance method for Interface
{
IInterface2 inter_object = null; //assigning NULL for the interface object
inter_object = new Class1(); //initialising the interface object to the class1()
return inter_object; //returning the interface object
}
}
In Main() Class add the following code :
IInterface2 newinter; //creating object for interface in class main()
FactoryClass factoryobj=new FactoryClass(); // creating object for factoryclass
In constructor add the following :
newinter=factoryobj.sample_display() // initialisingg the interface object with the instance method of factoryobj of FACTORY CLASS.
you can call the ffunction by using the following code :
newinter.display() //display() is the method in the interface.
Upvotes: 0
Reputation: 13216
Obviously you cannot create an instance of an interface, but if you were really trying to create an instance of the passed in class you could do this:
IAuditable j = ((IAuditable)Activator.CreateInstance(myObject.GetType()));
You need to know which concrete class to construct and in your example the only option is myObject.
Alternatively you could research something called 'Dependancy Injection' which allows you to specify which type of concrete class to "inject" into parameters that call out interfaces in constructors, or in fields. I'm not sure your total design, so this might be applicable. In Dependancy Injection you can state in your code IAuditables should be created using UserAudit, although there's a little more wireup than simply calling "new IAuditable"
Upvotes: 7
Reputation: 499262
You can't create an instance of an interface
Correct. You create an instance of an object implementing an interface:
IAuditable myUser = new User();
No where in the code does it define which IAudit applies to which IAuditable
You can't do this directly with just one interface. You will need to rethink your design.
You can use a open generic type in the interface and implement it with closed types:
public interface IAudit<T> {
DateTime DateCreated { get; set; }
}
public class UserAudit : IAudit<User> {
public string UserName { get; set; }
public DateTime DateCreated { get; set; }
public UserAdit(User user) {
UserName = user.UserName;
}
}
I can't specify that the IAudit interface must have a constructor which takes an IAuditable
Correct, you can't. See here. You need to create such a constructor on the implementers.
Upvotes: 19
Reputation: 5081
No where in the code does it define which IAudit applies to which IAuditable I can't specify that the IAudit interface must have a constructor which takes an IAuditable
You could fix these two by adding a CreateAudit()
function to your IAuditable
. Then you'd get an IAudit
created from the IAuditable
. As a bonus if you wanted to store a reference to the IAudit
in the IAuditable
(or vice-versa) so you can have them related to each other, it's pretty easy to have an implementing class do that. You could also add GetAuditable()
to IAudit
to get the IAuditable
it was created from, for example.
Simple implementation would look like this (on a class implementing IAuditable):
public IAudit CreateAudit()
{
UserAudit u = new UserAudit(UserName);
return u;
}
Upvotes: 18