internal member in an interface

2020-08-09 05:13发布

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?

12条回答
够拽才男人
2楼-- · 2020-08-09 05:30

Make another interface that is internal, and use explicit implementation for the method.

internal interface InternalIAM
{
    void Save();
}

public class concreteIAM : InternalIAM
{
    void InternalIAM.Save()
    {
    }
}
查看更多
男人必须洒脱
3楼-- · 2020-08-09 05:33

Maybe you want to separate the saving of your items into a different set of classes that are internal to your assembly:

internal interface IAMSaver { void Save(IAM item); }

internal class AMSaverFactory {
  IAMSaver GetSaver(Type itemType) { ... }
}

public class MyList : List<IAM>
{
  public void Save()
  {
    foreach (IAM itemin this)
    {
      IAMSaver saver = SaverFactory.GetSaver(item.GetType());
      saver.Save(item)
    }
  }
}
查看更多
甜甜的少女心
4楼-- · 2020-08-09 05:37

I don't think you should be using a interface here maybe you should be using an abstract base something like.:

public abstract class AM
{
    public int ID { get; set; }
    internal abstract void Save();
}

public class concreteIAM : AM
{
    internal override void Save()
    {
        //Do some save stuff
    }
}

Will still allow you to do this:

public class AMList : List<AM>
{
    public void SaveItems()
    {
        foreach (var item in this)
        {
            item.Save();
        }
    }
}
查看更多
家丑人穷心不美
5楼-- · 2020-08-09 05:39

I had similar situation and thought this could help. (not sure if this is not needed at this time or not)

This is a legit case for me: in case suppose there is an interface which has some API which is internal to the DLL and some API can be accessed from outside the DLL. Since interface is an abstract class, instead of defining as an interface you can define as a abstract class.

using System.Collections.Generic;

public abstract class IAM
{
    int ID { get; set; }
    internal abstract void Save();
}

public class concreteIAM : IAM
{
    public int ID { get; set; }
    internal override void Save()
    {
        //save the object
    }

    //other staff for this particular class
}

public class MyList : List<IAM>
{
     internal void Save()
    {
        foreach (IAM iam in this)
        {
            iam.Save();
        }
    }

    //other staff for this particular class
}
查看更多
淡お忘
6楼-- · 2020-08-09 05:39

I was wondering on the same issue here, and stumbled upon this question...

As i thought on this, i understood i don't need the internal method in the Interface in the first place.

I can access it through my Concrete Class, and leave the Contract for the Out-Side code.

In your example:

    public interface IAM
    {
            int ID { get; set; }
    }

    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 (concreteIAM iam in this)
                    {
                            iam.Save();
                    }
            }
            //other staff for this particular class
    }
查看更多
Juvenile、少年°
7楼-- · 2020-08-09 05:40

Why don't you use inner classes to control accessibility of your methods?

Example:

Your primary assembly

public abstract class Item
{
    public int ID { get; set; }
    protected abstract void Save();

    public class ItemCollection : List<Item>
    {
        public void Save()
        {
            foreach (Item item in this) item.Save();
        }
    }
}

Your secondary assembly

public sealed class NiceItem : Item
{
    protected override void Save()
    {
        // do something
    }
}

This pattern will still let you implement Save() method in other assemblies but only ItemCollection which is inner class of Item can call it. Brilliant, isn't it?

查看更多
登录 后发表回答