Puresharp عبارة عن مجموعة من الميزات لـ .NET 4.5.2+ / .NET Core 2.1 لتحسين الإنتاجية من خلال إنتاج تطبيقات مرنة وفعالة.
توفر Puresharp بشكل أساسي أدوات معمارية لبناء أساسيات التطبيقات الاحترافية:
وينقسم هذا الإطار إلى قسمين:
IPuresharp عبارة عن حزمة nuget مخصصة لإعادة كتابة التجميعات (باستخدام Mono.Cecil ) للسماح لها بأن تكون قابلة للتخصيص بشكل كبير في وقت التشغيل. لن يقوم IPuresharp بإضافة مرجع مكتبة جديد إلى التجميعات، ولكنه يتضمن فقط عملية إنشاء لاحقة لإعادة كتابة التجميعات تلقائيًا بعد نجاح البناء مباشرةً.
Install-Package IPuresharp -Version 5.0.5
يمكن استخدامه يدويًا مع سطر الأوامر لإدارة تجميعات الطرف الثالث
IPuresharp.exe "FullnameToAssembly.dll"
Puresharp عبارة عن حزمة nuget تقدم ميزات متنوعة مفيدة لتصميم بنية صحية ومنتجة. تتضمن هذه الحزمة أيضًا جميع المدفعية للتعامل بسهولة مع العناصر التي يجلبها كاتب IL IPuresharp. تضيف حزمة nuget مكتبة (Puresharp.dll) دون أي تبعيات أخرى.
Install-Package Puresharp -Version 5.0.5
ملاحظة: يوصى بتثبيت حزمة IPuresharp nuget في جميع المشاريع وتثبيت حزمة Puresharp nuget فقط في المشروع الذي تحتاج إليه بشكل صريح.
يتشابه سير العمل العالمي لحاوية DI مع الآخرين: قم بإعداد تركيبة وإنشاء حاوية وإنشاء مثيل لبعض المكونات من الحاوية.
مثال على الواجهات التي سيتم تكوينها
public interface IA
{
}
public interface IB
{
}
public interface IC
{
}
مثال على تطبيقات الارتباط بالواجهات
public class A : IA
{
public A(IB b, IC c)
{
}
}
public class B : IB
{
public B(IC c, int constant)
{
}
}
public class C : IC
{
}
إنشاء تركيبة
var _composition = new Composition();
تكوين الإعداد لـ IA وIB وIC على التوالي A وB وC
_composition.Setup<IA>(() => new A(Metadata<IB>.Value, Metadata<IC>.Value), Instantiation.Multiton);
_composition.Setup<IB>(() => new B(Metadata<IC>.Value, 28), Instantiation.Multiton);
_composition.Setup<IC>(() => new C(), Instantiation.Multiton);
قم بإنشاء حاوية من إعداد التكوين
var _container = _composition.Materialize();
إنشاء مثيل لوحدة نمطية من IA من الحاوية
using (var _module = _container.Module<IA>())
{
var _ia = _module.Value;
}
ملاحظة: الوحدة النمطية قابلة للIDisposable ودورة حياة crontrol لجميع التبعيات.
كيف تتم إدارة دورة الحياة للتبعيات؟ عندما يتم إعداد وحدة نمطية في تكوينها، يلزم وضع إنشاء مثيل ويمكن أن يكون Singleton (مثيل واحد مع دورة حياة مرتبطة بالحاوية)، أو Multiton (مثيل جديد لكل وحدة مع دورة حياة مرتبطة بالوحدة النمطية نفسها) أو Volatile (مثيل جديد دائمًا مع دورة الحياة المتعلقة بوحدة المالك). يمكن تحديد كل من الحاوية والوحدة النمطية لتحرير المكونات التي تم إنشاؤها.
هل تقوم واجهاتي بتطبيق IDisposable لتتناسب مع إدارة دورة الحياة؟ على العكس من ذلك، يجب ألا تقوم واجهة أحد المكونات مطلقًا بتنفيذ واجهة IDisposable التي تعد بمثابة اهتمام بالبنية التحتية البحتة. يمكن أن تكون التطبيقات فقط. تتأكد الحاوية من التخلص من عمليات التنفيذ بشكل صحيح عندما تقوم بتنفيذ واجهة IDisposable.
لماذا نستخدم تعبير لامدا لتكوين المكونات بدلاً من المعلمة العامة الكلاسيكية؟ يوفر تعبير Lambda طريقة لاستهداف المنشئ لاستخدامه، وتحديد متى يتم استخدام التبعيات والتقاط الثابت.
كيف يتم تكوين التبعية؟ ما عليك سوى استخدام Metadata<T>.Value في التعبير عندما تحتاج إلى استعادة التبعية من الحاوية.
هل يمنع حقن المنشئ الإشارة الدورية بين المكونات؟ لا، المراجع الدورية هي ميزة. عندما يتم إنشاء مثيل، فإن الأمر ليس كذلك حقًا، حيث يتم إعداد مثيل الوكيل البطيء لتقليل الاحتفاظ بالموارد غير المستخدمة والسماح بالمراجع الدورية.
في المعاينة، يتم استخدام المنشئين فقط لإعداد المكون، فهل يقتصر ذلك على حقن المنشئ؟ لا، التعبيرات مفتوحة تماما. يمكنك إدخال أساليب ثابتة ومنشئات وأعضاء وحتى مزج أنماط مختلفة.
سير العمل :
مثال للواجهة
[AttributeUsage(AttributeTargets.Method)]
public class Read : Attribute
{
}
[AttributeUsage(AttributeTargets.Method)]
public class Operation : Attribute
{
}
public interface IService
{
[Operation]
void SaveComment(int id, string text);
[Read]
[Operation]
string GetComment(int id);
}
مثال للتنفيذ
public class Service : IService
{
public void SaveComment(int id, string text)
{
}
public string GetComment(int id)
{
return null;
}
}
لنفترض أننا نريد تسجيل جميع عمليات القراءة فقط. لذلك، يتعين علينا تحديد Pointcut الذي يمثل جميع الأساليب التي يتم تشغيلها للقراءة فقط (حيث يتم وضع سمة القراءة وسمة العملية)
public class ReadonlyOperation : Pointcut.And<Pointcut<Operation>, Pointcut<Read>>
{
}
حدد نصيحة لتسجيل الدخول قبل استخدام Trace.WriteLine على سبيل المثال عند استدعاء الأساليب
public class Log : IAdvice
{
private MethodBase m_Method;
public Log(MethodBase method)
{
this.m_Method = method;
}
public void Instance<T>(T instance)
{
}
public void Argument<T>(ref T value)
{
}
public void Begin()
{
Trace.WriteLine(this.m_Method);
}
public void Await(MethodInfo method, Task task)
{
}
public void Await<T>(MethodInfo method, Task<T> task)
{
}
public void Continue()
{
}
public void Throw(ref Exception exception)
{
}
public void Throw<T>(ref Exception exception, ref T value)
{
}
public void Return()
{
}
public void Return<T>(ref T value)
{
}
public void Dispose()
{
}
}
حدد جانبًا يستخدم نصيحة السجل
public class Logging : Aspect
{
override public IEnumerable<Advisor> Manage(MethodBase method)
{
yield return Advice
.For(method)
.Around(() => new Log(method));
}
}
قم بإنشاء مثيل لـ Aspect ونسجه في ReadonlyOperation Pointcut الخاص بنا
var _logging = new Logging();
_logging.Weave<ReadonlyOperation>();
تهانينا، لقد تم الآن إدخال جانب التسجيل في جميع عقود التشغيل للقراءة فقط.
هنا مجموعة من العينات للسماح برؤية طرق مختلفة للإنشاء والاستشارة.
public class Logging : Aspect
{
override public IEnumerable<Advisor> Manage(MethodBase method)
{
//Use classic interceptor to create an 'Around' advisor (place break points in interceptor methods to test interception).
yield return Advice
.For(method)
.Around(() => new Interceptor());
//Use linq expression to generate a 'Before' advisor.
yield return Advice
.For(method)
.Before(invocation =>
{
return Expression.Call
(
Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)),
Expression.Constant($"Expression : { method.Name }")
);
});
//Use linq expression to generate a 'Before' advisor.
yield return Advice
.For(method)
.Before
(
Expression.Call
(
Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)),
Expression.Constant($"Expression2 : { method.Name }")
)
);
//Use ILGeneration from reflection emit API to generate a 'Before' advisor.
yield return Advice
.For(method)
.Before(advice =>
{
advice.Emit(OpCodes.Ldstr, $"ILGenerator : { method.Name }");
advice.Emit(OpCodes.Call, Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)));
});
//Use simple Action to generate a 'Before' advisor.
yield return Advice
.For(method)
.Before(() => Console.WriteLine($"Action : { method.Name }"));
//Use an expression to generate an 'After-Returning-Value' Advisor
yield return Advice
.For(method)
.After()
.Returning()
.Value(_Execution =>
{
return Expression.Call
(
Metadata.Method(() => Console.WriteLine(Metadata<string>.Value)),
Expression.Call
(
Metadata.Method(() => string.Concat(Metadata<string>.Value, Metadata<string>.Value)),
Expression.Constant("Returned Value : "),
Expression.Call(_Execution.Return, Metadata<object>.Method(_Object => _Object.ToString()))
)
);
});
//Validate an email parameter value.
yield return Advice
.For(method)
.Parameter<EmailAddressAttribute>()
.Validate((_Parameter, _Attribute, _Value) =>
{
if (_Value == null) { throw new ArgumentNullException(_Parameter.Name); }
try { new MailAddress(_Value.ToString()); }
catch (Exception exception) { throw new ArgumentException(_Parameter.Name, exception); }
});
}
}
هل يمكنني نسج جوانب متعددة في نفس Pointcut؟ نعم، فقط كن حذرًا بشأن ترتيب النسيج.
كيف يمكنني إزالة جانب من Pointcut؟ توجد طريقة إصدار محددة في Aspect للتخلص من Aspect من Pointcut .
هل السمات مطلوبة لتحديد Pointcut؟ لا، يمكن تعريف Pointcut عن طريق الوراثة مباشرة من Pointcut وتنفيذ مطابقة الطريقة المجردة التي تأخذ MethodBase كوسيطة واحدة وترجع قيمة منطقية للإشارة إلى ما إذا كانت الطريقة موجودة في نطاق Pointcut .
لماذا يجب علي استخدام IPuresharp؟ يعتمد الاعتراض على IPuresharp. في الواقع، أضاف IPuresharp إجراء بناء لإعادة كتابة CIL لجعل التجميع "صديقًا للمهندس المعماري" عن طريق حقن ميزات شفافة ومخفية لمنح التحكم الكامل في التنفيذ في وقت التشغيل.
هل يمكنني اعتراض المنشئ؟ إذا كانت الإجابة بنعم، كيف يمكنني تنفيذها؟ يتم دعم اعتراض المنشئ ويتم التعامل معه كطريقة أخرى مع الإعلان عن النوع كوسيطة أولى وباطل لنوع الإرجاع.
هل الأنواع والأساليب العامة مدعومة؟ يتم دعم الأنواع والأساليب العامة بشكل كامل عن طريق الحقن.
هل يمكنني اعتراض الطرق غير المتزامنة؟ يتم دعم أساليب عدم المزامنة بشكل كامل عن طريق الحقن وتوفر طريقة لاعتراض كل خطوة غير متزامنة.