Небольшой фон:
Моя цель - создать API в C #, который принимает два ввода:
- Два пользовательскихклассы, которые находятся в отдельном файле
.cs
и компилируются в определенном проекте.Этот проект создает, модифицирует и обычно выполняет любые манипуляции с объектами этих классов.Существует только два класса, потому что один отвечает за ввод пользовательского метода (см. Ниже), а другой - за его вывод - Пользовательские методы, которые работают с объектами классов, упомянутых выше.Эти методы дают определенный результат - объект класса, отвечающий за вывод.
И производит один вывод:
- Объекткласс, отвечающий за вывод.
Вот пример моих классов ввода-вывода:
namespace DummyIOClasses
{
#region IO_CLASSES
public class InputClass
{
public InputClass(List<double> vals)
{
tubeValues = new List<double>();
foreach (double val in vals)
{
tubeValues.Add(val);
}
}
public List<double> tubeValues;
}
public class OutputClass
{
public OutputClass()
{
warningsCards = new List<string>();
warningsTubes = new List<string>();
result = "N/A";
}
public List<string> warningsCards;
public List<string> warningsTubes;
public string result;
}
#endregion
}
А вот пример пользовательского метода:
public OutputClass GetOutput(InputClass input)
{
OutputClass output = new OutputClass();
double sum = 0;
foreach (double val in input.tubeValues)
{
if (val % 2 == 0)
{
output.warningsCards.Add("Divisible by 2!");
}
if (val % 3 == 0)
{
output.warningsTubes.Add("Divisible by 3!");
}
sum += val;
}
output.result = sum.ToString();
return output;
}
Мой API должен загружать разные методы, которые работают с одним и тем же набором классов ввода-вывода.Но всякий раз, когда я хочу переключиться на другой набор классов ввода-вывода и использовать другие пользовательские методы, которые были созданы для этого нового набора, я должен иметь возможность делать это с помощью кода во время выполнения.
Это похоже напродвинули это, чтобы реализовать, и я все еще довольно плохо знаком с C # ... К сожалению, я даже не знаю, с чего начать и что делать, чтобы достичь своей цели.
Итак, мой вопрос: Как реализовать такой API?Я не прошу решения, я прошу более опытных людей направлять меня в правильном направлении.Какие инструменты C # я должен использовать для этой задачи и как?
Достигнутый прогресс
Я реализовал класс, который принимает фиктивный .cs
файл с набором заполнителей для кода, который будет вставлен в будущем.Выглядит это так:
ASSEMBLY_PASTE
namespace ScriptInterpreter
{
CLASS_PASTE
public class Interpreter
{
METHOD_PASTE
}
}
Как видите, есть 3 заполнителя.Один для `использования xxxxxxx; 'операторы, один для пользовательских классов ввода-вывода и один для пользовательского метода, который работает с объектами этих классов.
Первый заполнитель прост, я заполняю List<string>
различных операторов использования во время выполнения, а затемвызовите метод, который заменяет заполнитель на эти операторы, довольно просто.
Что касается секундного заполнителя, я копирую код для классов ввода-вывода из отдельного файла .cs
проектов (код заключен в определенные#region, чтобы сделать это проще) и вставьте их вместо этого заполнителя.
Третий заполнитель еще проще, у меня есть файл .cs
, который никогда не компилируется и просто копируется в папку сборки,у него есть собственный метод, который работает с классами из моего проекта.Поэтому я просто копирую и вставляю весь файл вместо заполнителя.
После всех этих манипуляций файл результата выглядит следующим образом:
using System;
using System.Collections.Generic;
namespace ScriptInterpreter
{
public class InputClass
{
public InputClass(List<double> vals)
{
tubeValues = new List<double>();
foreach (double val in vals)
{
tubeValues.Add(val);
}
}
public List<double> tubeValues;
}
public class OutputClass
{
public OutputClass()
{
warningsCards = new List<string>();
warningsTubes = new List<string>();
result = "N/A";
}
public List<string> warningsCards;
public List<string> warningsTubes;
public string result;
}
public class Interpreter
{
public OutputClass GetOutput(InputClass input)
{
OutputClass output = new OutputClass();
double sum = 0;
foreach (double val in input.tubeValues)
{
if (val % 2 == 0)
{
output.warningsCards.Add("Divisible by 2!");
}
if (val % 3 == 0)
{
output.warningsTubes.Add("Divisible by 3!");
}
sum += val;
}
output.result = sum.ToString();
return output;
}
}
}
Затем я беру этот файл, помещаю его встроку, и используйте CSharpCodeProvier
для компиляции сборки из нее.
Получив сборку, я просто вызываю метод GetOutput
через нее с объектом пользовательского класса, которым я былс помощью.Вот так:
public object ExecuteMethod(object input)
{
object compiledAssembly = results.CompiledAssembly.CreateInstance("ScriptInterpreter.Interpreter");
MethodInfo methodInfo = compiledAssembly.GetType().GetMethod("GetOutput");
object output = methodInfo.Invoke(compiledAssembly, new object[] { input });
return output;
}
Но вот проблема!Типы разные!Хотя их поля и методы идентичны, в C # они отличаются, потому что они расположены в разных сборках и пространствах имен!
Итак, вот где я застрял прямо сейчас ... Я действительно не знаю, какинформировать эти две сборки о существовании друг друга или ... вы знаете ... заставить вещь работать!Я знаю, что может быть хакерское решение, например, преобразование всех данных в классе в строку и передача этой строки назад и вперед для создания объектов, но это последнее, что я хочу сделать, чтобы быть честным ...думаю, что должен быть лучший способ решения этой проблемы!
Если это возможно!
Я был бы очень признателен за вашу помощь с тем, что у меня уже есть.Потому что это именно тот API, который я планировал создать в первую очередь ...
Если вам это действительно интересно, вот полный код моего Interpreter
класса.
И пример использование вместе с IO Classes из какого-либо проекта и пользовательский метод для этих классов.