Поскольку это, кажется, популярный вопрос, вот полный пример исходного кода о том, как это сделать.
Предположим, что у нас есть сборка образцов, MyAssembly.dll , с класс MyClass . Мы хотим динамически загрузить его и вызвать его методы. Код MyAssembly :
namespace MyAssembly
{
public class MyClass
{
public int X { get; set; }
public int Y { get; set; }
public MyClass(int initialX, int initialY)
{
X = initialX;
Y = initialY;
}
public int MyMethod(int count, string text)
{
Console.WriteLine("This is a normal method.");
Console.WriteLine("Count: {0}", count);
Console.WriteLine("Text: {0}", text);
return this.X + this.Y;
}
public static void StaticMethod(int count, float radius)
{
Console.WriteLine("This is a static method call.");
Console.WriteLine("Count: {0}", count);
Console.WriteLine("Radius: {0}", radius);
}
}
}
Сначала мы хотели бы создать экземпляр класса с помощью конструктора MyClass(int initialX, int initialY)
, а затем вызвать метод public int MyMethod(int count, string text)
. Вот как вы это делаете из другого проекта (например, консольного приложения):
static void Main(string[] args)
{
//
// 1. Load assembly "MyAssembly.dll" from file path. Specify that we will be using class MyAssembly.MyClass
//
Assembly asm = Assembly.LoadFrom(@"C:\Path\MyAssembly.dll");
Type t = asm.GetType("MyAssembly.MyClass");
//
// 2. We will be invoking a method: 'public int MyMethod(int count, string text)'
//
var methodInfo = t.GetMethod("MyMethod", new Type[] { typeof(int), typeof(string) });
if (methodInfo == null)
{
// never throw generic Exception - replace this with some other exception type
throw new Exception("No such method exists.");
}
//
// 3. Define parameters for class constructor 'MyClass(int initialX, int initialY)'
//
object[] constructorParameters = new object[2];
constructorParameters[0] = 999; // First parameter.
constructorParameters[1] = 2; // Second parameter.
//
// 4. Create instance of MyClass.
//
var o = Activator.CreateInstance(t, constructorParameters);
//
// 5. Specify parameters for the method we will be invoking: 'int MyMethod(int count, string text)'
//
object[] parameters = new object[2];
parameters[0] = 124; // 'count' parameter
parameters[1] = "Some text."; // 'text' parameter
//
// 6. Invoke method 'int MyMethod(int count, string text)'
//
var r = methodInfo.Invoke(o, parameters);
Console.WriteLine(r);
}
Вызов статического метода public static void StaticMethod(int count, float radius)
выглядит так:
var methodInfoStatic = t.GetMethod("StaticMethod");
if (methodInfoStatic == null)
{
// never throw generic Exception - replace this with some other exception type
throw new Exception("No such static method exists.");
}
// Specify parameters for static method: 'public static void MyMethod(int count, float radius)'
object[] staticParameters = new object[2];
staticParameters[0] = 10;
staticParameters[1] = 3.14159f;
// Invoke static method
methodInfoStatic.Invoke(o, staticParameters);
Я бы предпочел сделать это в два этапа: во-первых, создать один узел для каждой пары имени и номера, чтобы у нас было что-то вроде:
<amount name="AAA" value="3755.45"/>
<amount name="BBB" value="817633.21"/>
<amount name="AAA" value="200.03"/>
<amount name="CCC" value="20"/>
<amount name="BBB" value="13072806.23"/>
<amount name="AAA" value="10"/>
Следующим шагом является применение [ 114] мюнхенская группировка к результату.
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="amt-by-name" match="amount" use="@name" />
<xsl:template match="/root">
<!-- FIRST PASS -->
<xsl:variable name="amounts">
<xsl:for-each select="object/*[position() mod 2 = 1]">
<amount name="{.}" value="{following-sibling::*}"/>
</xsl:for-each>
</xsl:variable>
<!-- OUTPUT -->
<output>
<!-- FOR EACH DISTINCT NAME -->
<xsl:for-each select="exsl:node-set($amounts)/amount[count(. | key('amt-by-name', @name)[1]) = 1]">
<!-- SUM CURENT GROUP -->
<sum name="{@name}" value="{sum(key('amt-by-name', @name)/@value)}"/>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
Применяется к правильно сформированному (!) примеру входа:
XML
<root>
<object>
<NUM-1054>AAA</NUM-1054>
<NUM-1054>3755.45</NUM-1054>
<NUM-601>BBB</NUM-601>
<NUM-601>817633.21</NUM-601>
<NUM-1072>AAA</NUM-1072>
<NUM-1072>200.03</NUM-1072>
<NUM-11072>CCC</NUM-11072>
<NUM-11072>20</NUM-11072>
<NUM-900>BBB</NUM-900>
<NUM-900>13072806.23</NUM-900>
<NUM-11074>AAA</NUM-11074>
<NUM-11074>10</NUM-11074>
</object>
</root>
это даст:
Результат
<?xml version="1.0" encoding="UTF-8"?>
<output>
<sum name="AAA" value="3965.48"/>
<sum name="BBB" value="13890439.44"/>
<sum name="CCC" value="20"/>
</output>