假设我有声明内部接口IInternalInterface
的程序集。我无法访问此程序集的代码,我无法更改它。
如何创建自己的IInternalInterface
实现?
为什么我需要这个:程序集包含带有IInternalInterface
实现者列表的类,我的目标是在那里添加我自己的实现。
答案 0 :(得分:9)
可以使用远程代理 请注意,我的答案只是一个快速草图,可能需要进一步改进。
internal interface IInternalInterface {
void SayHello();
}
// --------------------------------------------------------------
// in another assembly
public class ImplementationProxy : RealProxy, IRemotingTypeInfo {
private readonly MethodInfo method;
public ImplementationProxy(MethodInfo method)
: base(typeof(ContextBoundObject))
{
this.method = method;
}
public override IMessage Invoke(IMessage msg) {
if (!(msg is IMethodCallMessage))
throw new NotSupportedException();
var call = (IMethodCallMessage)msg;
if (call.MethodBase != this.method)
throw new NotSupportedException();
Console.WriteLine("Hi from internals!");
return new ReturnMessage(null, null, 0, call.LogicalCallContext, call);
}
public bool CanCastTo(Type fromType, object o)
{
return fromType == method.DeclaringType;
}
public string TypeName
{
get { return this.GetType().Name; }
set { }
}
}
答案 1 :(得分:3)
如何创建自己的IInternalInterface实现?
简单回答:你做不到。如果程序集的作者决定用internal
标记此接口,则意味着他们不希望其他程序集中的代码使用此接口。
答案 2 :(得分:3)
我会延长@AndreyShchekin的答案,因为它非常有用,但遗漏了一些内容:
public class Program
{
public static void Main()
{
var internalType = typeof(PublicTypeInAnotherAssembly).Assembly.GetType("Full name of internal type: System.Internals.IInterface");
var result = new InterfaceImplementer(internalType, InterfaceCalled).GetTransparentProxy();
}
static object InterfaceCalled(MethodInfo info)
{
// Implement logic.
Console.WriteLine($"{info.Name}: Did someone call an internal method?");
// Return value matching info.ReturnType or null if void.
return null;
}
}
public class InterfaceImplementer : RealProxy, IRemotingTypeInfo
{
readonly Type _type;
readonly Func<MethodInfo, object> _callback;
public InterfaceImplementer(Type type, Func<MethodInfo, object> callback) : base(type)
{
_callback = callback;
_type = type;
}
public override IMessage Invoke(IMessage msg)
{
var call = msg as IMethodCallMessage;
if (call == null)
throw new NotSupportedException();
var method = (MethodInfo)call.MethodBase;
return new ReturnMessage(_callback(method), null, 0, call.LogicalCallContext, call);
}
public bool CanCastTo(Type fromType, object o) => fromType == _type;
public string TypeName { get; set; }
}
现在result
可分配给内部接口。为了验证它,我们可以在包含内部接口的程序集中执行此操作:
public class PublicTypeInAnotherAssembly
{
public void Test(object proxy)
{
var internalInterface = (IInternalInterface)proxy;
internalInterface.MethodOnInterface();
}
}
如果我们无法访问,请使用反射进行分配。
答案 3 :(得分:0)
您还可以使用程序集版本重定向或类型重定向将接口声明“移动”到您控制下的程序集中,并使您的实现公开。
但正如达林所说,一定要仔细考虑这种方法。可能有一种扩展库功能的预期方法会更加清晰......
答案 4 :(得分:0)
恐怕这是不可能的。即使您设法使用Reflection.Emit创建一个实现该接口的类,您也将无法使用它,因为您将获得ReflectionTypeLoadException: Type is attempting to implement an inaccessible interface
答案 5 :(得分:-1)
您可以添加[InternalsVisibleTo()]
属性,但只要您无法访问源代码,就无法在编译时实现此接口 < / p>
另一方面,您可以在运行时执行此操作。为此,您应该使用运行时代码生成(也称为Reflection.Emit
)并获取接口类型BindingFlags.NonPublic
。您可以阅读更多相关信息here。 击>
<强>更新:强>
如下面的评论中所述,不可能从非公共接口继承。很遗憾,你有没有解决方案。