I have a list of objects implementing an interface, and a list of that interface:
public interface IAM
{
int ID { get; set; }
void Save();
}
public class concreteIAM : IAM
{
public int ID { get; set; }
internal void Save(){
//save the object
}
//other staff for this particular class
}
public class MyList : List<IAM>
{
public void Save()
{
foreach (IAM iam in this)
{
iam.Save();
}
}
//other staff for this particular class
}
The previous code doesn't compile because the compiler requires all the interface members to be public.
internal void Save(){
But i don't want to allow the from outside my DLL to save the ConcreteIAM
, it only should be saved through the MyList
.
Any way to do this?
Update#1: Hi all, thanks for the answers so far, but none of them is exactly what i need:
The interface needs to be public because it is the signature the client from outside the dll will use, along with ID
and other properties i didn't bother to write in the example to keep it simple.
Andrew, I don't think the solution is create a factory to create another object that will contain the IAM
members + Save. I am still thinking... Any other ideas?
It is exactly what I am talking about in my article Friends and internal interface members at no cost with coding to interfaces.
The essence from the article
From now one only your assembly can call the
Save()
method, since an instance of theInternal
class can only be created by your assembly.Interface members are supposed to be public.. anything else and you should be thinking if you need something else. In this case, you
Keeping design thoughts aside, you could do this via Explicit Interface Implementation.
IPersist is internal, not available outside the parent assembly and since it is explicitly implemented, it cannot be called without an IPersist reference.
Update From your latest response, we have more constraints. The Interface must be public, it should contain the Save method, which shouldn't be publicly available. I'd say go back to the drawing board... something doesn't seem right. IMHO You can't do this with a single interface. How about splitting into 2 interfaces, the public one and the internal one?
Go with two interfaces:
The implementation of Save() must be explicit to prevent clients calling it.
I think the best thing to do would be to break the internal and public members into two separate interfaces. If you inherit the interfaces you can still declare the members publicly but the visibility of the internal members will be dictated by the visibility of the interface itself.
If you don't want external callers to be able to call your Save() method, why not make the whole concreteIAM class internal?
Or, if you want the class public, but not the interface, make the whole interface internal. I think an internal interface can be added to a public class (but I haven't tried it...)
I think you don't understand what an interface is for. Interface is a contract. It specifies that an object behaves in a certain way. If an object implements an interface, it means that you can rely on it that it has all the interface's methods implemented.
Now, consider what would happen if there was an interface like you're asking for - public, but with one internal member. What would that mean? An external object could implement only the public methods, but not the internal one. When you would get such an external object, you would be able to call only the public methods, but not the internal one, because the object couldn't implement it. In other words - the contract would not be fulfilled. Not all of the methods would be implemented.
I think that the solution in this case is to split your interface in two. One interface would be public, and that's what your external objects would implement. The other interface would be internal and would contain your
Save()
and other internal methods. Perhaps this second interface could even inherit from the first. Your own internal objects would then implement both interfaces. This way you could even distinguish between external objects (ones that don't have the internal interface) and internal objects.