background
Released three years ago C#8.0 There is an important improvement in... Called Interface default implementation , From then on , The method defined in the interface can contain the method body , Default implementation . But for the default implementation of the interface , The implementation class or sub interface cannot override this method base call , Just like subclass overriding methods can be base.Method() like that . for example :
public interface IService
{
void Proccess()
{
Console.WriteLine("Proccessing");
}
}
public class Service : IService
{
public void Proccess()
{
Console.WriteLine("Before Proccess");
base(IService).Proccess(); // Currently not supported , It is also the part that this article needs to discuss
Console.WriteLine("End Proccess");
}
}The original C# The team listed this feature as a plan for the next step ( Click here to view details ), However, three years later, it has not been put on the agenda . The lack of this feature is undoubtedly a great limitation , Sometimes we do need interfaces base Call to implement certain requirements . This article will introduce two ways to implement it .
Method 1: Use reflection to find the interface implementation and call it
The core idea of this method is , Use reflection to find the interface implementation you need to call MethodInfo, And then build DynamicMethod Use OpCodes.Call Just call it .
First, we define the method signature used to represent the interface method base call .
public static void Base<TInterface>(this TInterface instance, Expression<Action<TInterface>> selector);
public static TReturn Base<TInterface, TReturn>(this TInterface instance, Expression<Func<TInterface, TReturn>> selector);So the example in the previous section can be rewritten as :
public class Service : IService
{
public void Proccess()
{
Console.WriteLine("Before Proccess");
this.Base<IService>(m => m.Proccess());
Console.WriteLine("End Proccess");
}
}So next , We need the basis lambda Expression to find its corresponding interface implementation , And then call it .
The first step is based on lambda Expression acquisition MethodInfo And parameters . It should be noted that , We also need to support the calling of attributes , In fact, attributes are also a method , So it can be handled together .
private static (MethodInfo method, IReadOnlyList<Expression> args) GetMethodAndArguments(Expression exp) => exp switch
{
LambdaExpression lambda => GetMethodAndArguments(lambda.Body),
UnaryExpression unary => GetMethodAndArguments(unary.Operand),
MethodCallExpression methodCall => (methodCall.Method!, methodCall.Arguments),
MemberExpression { Member: PropertyInfo prop } => (prop.GetGetMethod(true) ?? throw new MissingMethodException($"No getter in propery {prop.Name}"), Array.Empty<Expression>()),
_ => throw new InvalidOperationException("The expression refers to neither a method nor a readable property.")
}; The second step , utilize Type.GetInterfaceMap Get the interface implementation method to be called . The key points to note here are ,instanceType.GetInterfaceMap(interfaceType).InterfaceMethods All methods of the interface will be returned , So you can't just match by method name , Because there may be various overloads 、 The generic parameter 、 also new Keyword to declare a method with the same name , So you can follow the Method name + Declaration type + Method parameter + Method generic parameters The only way to determine ( In the following code block IfMatch The implementation of the )
internal readonly record struct InterfaceMethodInfo(Type InstanceType, Type InterfaceType, MethodInfo Method);
private static MethodInfo GetInterfaceMethod(InterfaceMethodInfo info)
{
var (instanceType, interfaceType, method) = info;
var parameters = method.GetParameters();
var genericArguments = method.GetGenericArguments();
var interfaceMethods = instanceType
.GetInterfaceMap(interfaceType)
.InterfaceMethods
.Where(m => IfMatch(method, genericArguments, parameters, m))
.ToArray();
var interfaceMethod = interfaceMethods.Length switch
{
0 => throw new MissingMethodException($"Can not find method {method.Name} in type {instanceType.Name}"),
> 1 => throw new AmbiguousMatchException($"Found more than one method {method.Name} in type {instanceType.Name}"),
1 when interfaceMethods[0].IsAbstract => throw new InvalidOperationException($"The method {interfaceMethods[0].Name} is abstract"),
_ => interfaceMethods[0]
};
if (method.IsGenericMethod)
interfaceMethod = interfaceMethod.MakeGenericMethod(method.GetGenericArguments());
return interfaceMethod;
} The third step , Use the obtained interface method , structure DynamicMethod. The emphasis is on using OpCodes.Call, It means to call a method in a non - virtual way , Even if the method is virtual , And don't look for a rewrite of it , Instead, it calls itself directly .
private static DynamicMethod GetDynamicMethod(Type interfaceType, MethodInfo method, IEnumerable<Type> argumentTypes)
{
var dynamicMethod = new DynamicMethod(
name: "__IL_" + method.GetFullName(),
returnType: method.ReturnType,
parameterTypes: new[] { interfaceType, typeof(object[]) },
owner: typeof(object),
skipVisibility: true);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
var i = 0;
foreach (var argumentType in argumentTypes)
{
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldc_I4, i);
il.Emit(OpCodes.Ldelem, typeof(object));
if (argumentType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, argumentType);
}
++i;
}
il.Emit(OpCodes.Call, method);
il.Emit(OpCodes.Ret);
return dynamicMethod;
} Last , take DynamicMethod The conversion to strongly typed delegates is complete . Considering the optimization of performance , The final delegate can be cached , You don't have to build it again next time .
Method 2: Using function pointers
This method and method 1 Be the same in essentials while differing in minor points , The difference is that , In the method 1 The second step , That is, to find the interface method MethodInfo after , Get its function pointer , Then use this pointer to construct a delegate . This method is actually the method I first found , Method 1 Is its improvement . There is no more introduction here
Method 3: utilize Fody Interface methods are modified at compile time IL Of call call
Method 1 It's possible , But the visible performance loss is large , Even with caching . So I used Fody Write a plug-in InterfaceBaseInvoke.Fody.
The core idea is to find the target interface method at compile time , And then use call Just call it with the command . This minimizes performance loss . For the usage of this plug-in, please refer to Project introduction .
Performance testing
| Method | The average time | Memory allocation |
| Of the parent class base call | 0.0000 ns | - |
| Method 1(DynamicMethod) | 691.3687 ns | 776 B |
| Method 2(FunctionPointer) | 1,391.9345 ns | 1,168 B |
| Method 3(InterfaceBaseInvoke.Fody) | 0.0066 ns | - |
summary
This paper discusses several methods to realize the interface base Method called , Among them, the performance is InterfaceBaseInvoke.Fody The best , stay C# The official support has previously recommended . Welcome to use , Be careful , Thank you. .
【 Bowing C#】 How to implement the interface base Call more related articles
- Use base. Call the properties in the parent class
Use base. Call the properties in the parent class public class parent { public string a; }public class child :parent { public string g ...
- loadrunner do webservice A simple call to an interface
Today, I heard from Dashen webservice Interface , I simulated the actual combat according to what he said , There may be a lot more wrong , In general use webservice Interface , Will use soapui, But it has been used. loadrunner Later discovered lr Soon ...
- Calling remote services using interfaces ------ Using dynamic invocation of services , Realization .net It's like Dubbo How to play .
Distributed microservices are now the first of many corporate architectures , As far as I know , quite a lot java The company structure is Maven+Dubbo+Zookeeper On the basis of . Dubbo yes Alibaba Open source distributed service framework , Its biggest feature is to press ...
- Java WebService Interface generation and invocation Graphic, >【 turn 】【 To be adjusted 】
webservice brief introduction : Web Service technology , It can make different applications run on different machines without the aid of additional . Specialized third-party software or hardware , You can exchange data or integrate with each other . basis Web Service Between the application of specification implementation ...
- java Interface docking —— Others call our interface to get data
java Interface docking —— Others call our interface to get data , We need to develop several interfaces in our system , Provide the other party with interface specification documents , Including access to our interface address , And input parameter name and format , And the status of our return , Interface code : package ...
- .net WebServer Examples and calls ( Interface WSDL Dynamic invocation JAVA)
newly build .asmx page using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...
- php Of swoole Extension onclose and onconnect Interface is not called
In use swoole There was a problem when writing an online chat example , I checked a lot of information , Now record here . By looking at swoole_server Interface documentation , Callback registration interface on There are clear notes in the : * swoole_server-& ...
- according to URL Get parameter value json Result set , Give an interface to others to call
background : When testing the interface , It is often the back end get\post Request direct return json Result set , I really want to know how to implement it , Although my heart probably knows how to achieve , But it's better to do it yourself ! Let's take a look at the results first : The following is a web Of get Interface entry ...
- 《React Backstage management system real combat : 3、 ... and 》header Components : Page layout 、 Weather request interface and page call 、 Time format and use of timers 、 Exit function
One . Layout and typesetting 1. Layout src/pages/admin/header/index.jsx import React,{Component} from 'react' import './header. ...
- webservice wsdl Interface configuration and call
Preparation package WebRoot/WEB-INF/lib/axis2-adb-1.6.2.jarWebRoot/WEB-INF/lib/axis2-ant-plugin-1.6.2.jarWebRoot/WEB ...
Random recommendation
- Allegro It cannot be saved ( The prompt is related to the user or lock of )
This happens unintentionally during use But when I reopened the file, I found brd Under the file is a .brd.lck file , Easily deleted , Return to normal ~ This is a bug Explain bug, The specific method will be studied carefully next time ~ Make it a good habit to save manually every few minutes , prevent b ...
- MVC Appears after upgrade " Does not exist in the current context ViewBag" To solve the problem
Take your project from MVC4 Upgrade to MVC5, As a result, there are a lot of problems ,View The design environment has emerged " Does not exist in the current context ViewBag" The problem of : Although it does not affect the compilation , But I always feel bad about it , And there are no grammatical hints ...
- Give Way TextView There is a running lantern effect
Only need TextView You can add some properties to : <?xml version="1.0" encoding="utf-8"?> <LinearLa ...
- weblogic11g Install cluster —— win2003 System 、 Single host
weblogic11g Install cluster —— win2003 System . Single host Be careful : This is a weblogic11g stay win2003 Under the system ( A mainframe ) Installation cluster of ,linux.hpux.aix And multiple hosts ...
- Java Programming idea - Chapter four exercises
practice 1: Write a program , Print from 1 To 100 Value public class Print1To100{ public static void main(String args[]){ for(int i = 1 ...
- iOS Performance optimization of development
1. Avoid being too large XIB When loading XIB I put all my things in the memory , Include any pictures : If there is one that won't be used immediately view, It will waste precious memory resources . When loading a reference to a picture or sound resource nib when ,nib ...
- VMWare Workstation: LAN PC Connect to the remote desktop or port in the virtual machine
It's simple . Make an understanding : 1.NAT 2.VM Network card of , It's like a router Environmental Science : Physical router :192.168.0.1 PC1(win):192.168.0.2 PC2(win):192.168.0.3 PC2 in ...
- ubuntu Set up vpn
Baidu has information http://jingyan.baidu.com/article/fa4125aca7f1b628ad709271.html 1. Set up VPN CONNECTION 2.configur ...
- Win8 cannot access xp Shared solutions ——win8 Internet neighbors visit other xp The computer needs a user name and password to cancel
New clothes win8, The original win7 Normal connection xp Sharing of downloaders , But in win8 I can't access it when I go down to the Internet xp The share of , Show ” Username or password incorrect ”, And the password is clearly right, as shown in the figure : resolvent : Press Win+R Startup and operation , transport secp ...
- Microsoft Azure Storage architecture design
SQL Azure brief introduction SQL Azure yes Azure The logical database of the storage platform , The physical database is still SQL Server. A physical one SQL Server Divided into logical pieces (partition), Each piece becomes ...
![buuctf [GlassFish]任意文件读取](/img/37/e3c127f2f2ba97c5ca0b6cf01cf9ab.png)
![buuctf [PHP]CVE-2019-11043](/img/ba/d97fe48acfd20daa66d47f34d99cf1.png)





![buuctf [Jupyter]notebook-rce](/img/fc/9c2047bdadb606b555e48f553fb1dd.png)
![buuctf [PHP]inclusion](/img/02/d328ed84e4641c09c5b1eba3ac6ea9.png)
