Попробуйте вот так:
const stateMap = (state) => {
console.log('state', state);
return {
//something from state
};
};
export default connect(stateMap)(App);
Лучшим решением для C # / всех статических языков .NET является использование CodeDOM для таких вещей. (В качестве примечания, его другая основная цель заключается в динамическом построении битов кода или даже целых классов.)
Вот хороший пример из блога LukeH , который использует некоторые LINQ тоже просто для удовольствия.
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
class Program
{
static void Main(string[] args)
{
var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v3.5" } });
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll" }, "foo.exe", true);
parameters.GenerateExecutable = true;
CompilerResults results = csc.CompileAssemblyFromSource(parameters,
@"using System.Linq;
class Program {
public static void Main(string[] args) {
var q = from i in Enumerable.Range(1,100)
where i % 2 == 0
select i;
}
}");
results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.ErrorText));
}
}
Класс первостепенной важности здесь - CSharpCodeProvider
, который использует компилятор для компиляции кода «на лету». Если вы хотите запустить код, вам просто нужно использовать немного отражения для динамической загрузки сборки и ее выполнения.
Здесь - еще один пример на C #, который (хотя чуть менее кратким) дополнительно показывает вам, как запустить исполняемый код во время выполнения, используя пространство имен System.Reflection
.
Другие уже дали хорошие ответы о том, как сгенерировать код во время выполнения, поэтому я подумал, что рассмотрю ваш второй абзац. У меня есть некоторый опыт в этом и просто хочу поделиться уроком, который я извлек из этого опыта.
По крайней мере, я мог бы определить интерфейс, который им потребуется для реализации, тогда они предоставить раздел «код», который реализовал этот интерфейс.
blockquote>У вас может быть проблема, если вы используете
interface
в качестве базового типа. Если вы добавите новый метод кinterface
в будущем, все существующие классы, поставляемые клиентом, которые реализуютinterface
, теперь станут абстрактными, что означает, что вы не сможете скомпилировать или создать экземпляр класса, поставляемого клиентом во время выполнения.У меня возникла эта проблема, когда пришло время добавить новый метод примерно через год после отправки старого интерфейса и после распределения большого количества «старых» данных, которые необходимо было поддерживать. Я закончил создание нового интерфейса, унаследованного от старого, но этот подход усложнил загрузку и создание экземпляров классов, предоставленных клиентом, потому что мне пришлось проверить, какой интерфейс доступен.
Одно из решений, о которых я думал в то время было вместо этого использовать фактический класс как базовый тип, такой как тот, который приведен ниже. Сам класс может быть помечен как абстрактный, но все методы должны быть пустыми виртуальными методами (а не абстрактными методами). Клиенты могут затем переопределять методы, которые они хотят, и я могу добавить новые методы в базовый класс, не делая недействительным существующий код, поставляемый клиентом.
public abstract class BaseClass { public virtual void Foo1() { } public virtual bool Foo2() { return false; } ... }
Независимо от того, применяется ли эта проблема, вы должны подумать о том, как модифицировать интерфейс между вашей базой кода и кодом, поставляемым клиентом.
Нашел это полезным - гарантирует, что скомпилированная сборка ссылается на все, на что вы ссылаетесь в данный момент, поскольку есть хороший шанс, что вы хотите, чтобы C #, который вы компилируете, использовал некоторые классы и т. д. в коде, который испускает это:
var refs = AppDomain.CurrentDomain.GetAssemblies();
var refFiles = refs.Where(a => !a.IsDynamic).Select(a => a.Location).ToArray();
var cSharp = (new Microsoft.CSharp.CSharpCodeProvider()).CreateCompiler();
var compileParams = new System.CodeDom.Compiler.CompilerParameters(refFiles);
compileParams.GenerateInMemory = true;
compileParams.GenerateExecutable = false;
var compilerResult = cSharp.CompileAssemblyFromSource(compileParams, code);
var asm = compilerResult.CompiledAssembly;
В моем случае я выбрал класс, имя которого было сохранено в строке, className
, которая имела один открытый статический метод с именем Get()
, который возвращался с типом StoryDataIds
. Вот как выглядит этот метод:
var tempType = asm.GetType(className);
var ids = (StoryDataIds)tempType.GetMethod("Get").Invoke(null, null);
Пространство имен System.CodeDom.Compiler должно помочь. См. в этой статье
Для компиляции вы можете просто инициировать вызов оболочки для компилятора csc.
РЕДАКТИРОВАТЬ: Или еще лучше , используйте CodeDOM, как предложил Нолдорин ...
Вы можете скомпилировать фрагмент кода C # в память и сгенерировать байты сборки с Roslyn. Это уже упоминалось, но стоило бы добавить пример Roslyn для этого здесь. Ниже приведен полный пример:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
namespace RoslynCompileSample
{
class Program
{
static void Main(string[] args)
{
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(@"
using System;
namespace RoslynCompileSample
{
public class Writer
{
public void Write(string message)
{
Console.WriteLine(message);
}
}
}");
string assemblyName = Path.GetRandomFileName();
MetadataReference[] references = new MetadataReference[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(typeof(Enumerable).Assembly.Location)
};
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
}
else
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = Assembly.Load(ms.ToArray());
Type type = assembly.GetType("RoslynCompileSample.Writer");
object obj = Activator.CreateInstance(type);
type.InvokeMember("Write",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
obj,
new object[] { "Hello World" });
}
}
Console.ReadLine();
}
}
}