मैं बिल्कुल वही कर रहा हूं जो आप मेरे नियम इंजन में देख रहे हैं, जो गतिशील रूप से संकलन, लोड करने और C # चलाने के लिए CS-Script का उपयोग करता है। यह आसानी से अनुवाद योग्य होना चाहिए कि आप क्या खोज रहे हैं, और मैं एक उदाहरण दूंगा। सबसे पहले, कोड (छीन लिया गया):
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using CSScriptLibrary;
namespace RulesEngine
{
public class RulesEngine<T> where T : class
{
public RulesEngine(string rulesScriptFileName, string classToInstantiate)
: this()
{
if (rulesScriptFileName == null) throw new ArgumentNullException("rulesScriptFileName");
if (classToInstantiate == null) throw new ArgumentNullException("classToInstantiate");
if (!File.Exists(rulesScriptFileName))
{
throw new FileNotFoundException("Unable to find rules script", rulesScriptFileName);
}
RulesScriptFileName = rulesScriptFileName;
ClassToInstantiate = classToInstantiate;
LoadRules();
}
public T @Interface;
public string RulesScriptFileName { get; private set; }
public string ClassToInstantiate { get; private set; }
public DateTime RulesLastModified { get; private set; }
private RulesEngine()
{
@Interface = null;
}
private void LoadRules()
{
if (!File.Exists(RulesScriptFileName))
{
throw new FileNotFoundException("Unable to find rules script", RulesScriptFileName);
}
FileInfo file = new FileInfo(RulesScriptFileName);
DateTime lastModified = file.LastWriteTime;
if (lastModified == RulesLastModified)
{
return;
}
string rulesScript = File.ReadAllText(RulesScriptFileName);
Assembly compiledAssembly = CSScript.LoadCode(rulesScript, null, true);
@Interface = compiledAssembly.CreateInstance(ClassToInstantiate).AlignToInterface<T>();
RulesLastModified = lastModified;
}
}
}
यह टाइप T का एक इंटरफ़ेस लेगा, एक .cs फ़ाइल को असेंबली में संकलित करेगा, किसी दिए गए प्रकार के एक वर्ग को तुरंत कर सकता है, और उस तत्काल वर्ग को T इंटरफ़ेस में संरेखित कर सकता है। मूल रूप से, आपको बस यह सुनिश्चित करना होगा कि तत्काल वर्ग उस इंटरफ़ेस को लागू करता है। मैं गुणों का उपयोग सेटअप और सब कुछ एक्सेस करने के लिए करता हूं, जैसे:
private RulesEngine<IRulesEngine> rulesEngine;
public RulesEngine<IRulesEngine> RulesEngine
{
get
{
if (null == rulesEngine)
{
string rulesPath = Path.Combine(Application.StartupPath, "Rules.cs");
rulesEngine = new RulesEngine<IRulesEngine>(rulesPath, typeof(Rules).FullName);
}
return rulesEngine;
}
}
public IRulesEngine RulesEngineInterface
{
get { return RulesEngine.Interface; }
}
अपने उदाहरण के लिए, आप रन () को कॉल करना चाहते हैं, इसलिए मैं एक इंटरफ़ेस बनाऊंगा जो रन () विधि को परिभाषित करता है, जैसे:
public interface ITestRunner
{
void Run();
}
फिर एक वर्ग बनाएं जो इसे लागू करता है, जैसे:
public class TestRunner : ITestRunner
{
public void Run()
{
}
}
TestHarness की तरह कुछ नियमों के नियम बदलें, और अपने गुण सेट करें:
private TestHarness<ITestRunner> testHarness;
public TestHarness<ITestRunner> TestHarness
{
get
{
if (null == testHarness)
{
string sourcePath = Path.Combine(Application.StartupPath, "TestRunner.cs");
testHarness = new TestHarness<ITestRunner>(sourcePath , typeof(TestRunner).FullName);
}
return testHarness;
}
}
public ITestRunner TestHarnessInterface
{
get { return TestHarness.Interface; }
}
फिर, कहीं भी आप इसे कॉल करना चाहते हैं, आप बस चला सकते हैं:
ITestRunner testRunner = TestHarnessInterface;
if (null != testRunner)
{
testRunner.Run();
}
यह शायद एक प्लगइन सिस्टम के लिए बहुत अच्छा काम करेगा, लेकिन जैसा कि मेरा कोड एक फ़ाइल लोड करने और चलाने तक सीमित है, क्योंकि हमारे सभी नियम एक सी # स्रोत फ़ाइल में हैं। मुझे लगता है कि इसे संशोधित करना बहुत आसान होगा, बस इसे टाइप / सोर्स फाइल में पास करना होगा हर एक के लिए जिसे आप चलाना चाहते थे। आपको बस कोड को गेट्टर से एक विधि में स्थानांतरित करना होगा जो उन दो मापदंडों को ले गया।
इसके अलावा, ITestRunner के स्थान पर अपने IRunnable का उपयोग करें।
export
औरimport
एक ज्ञात इंटरफ़ेस से प्राप्त होने वाली अलग-अलग विधानसभाओं में कक्षाएं