سلام
من ViewModel استفاده کردم و ViewModelها را هم در یک فایل مجزا و داخل پروژه DataLayer تعریف کرده ام ، با توضیحات شما ViewModel خود یک پروژه مجزا مثل DataLayer بشود، صحیحتر است و یا در خود پروژه اصلی تعریف شود؟
سلام
من ViewModel استفاده کردم و ViewModelها را هم در یک فایل مجزا و داخل پروژه DataLayer تعریف کرده ام ، با توضیحات شما ViewModel خود یک پروژه مجزا مثل DataLayer بشود، صحیحتر است و یا در خود پروژه اصلی تعریف شود؟
namespace MvcHealthCheckTest.Controllers { public class HomeController : Controller { public IActionResult ViewDetails() { return View(); }
<a asp-controller="Home" asp-action="ViewDetails">View Details</a>
https://localhost:5001/Home/ViewDetails
using System.Text.RegularExpressions; using Microsoft.AspNetCore.Routing; public class CustomUrlTransformer : IOutboundParameterTransformer { public string TransformOutbound(object value) { return value == null ? null : Regex.Replace(value.ToString(), "([a-z])([A-Z])", "$1-$2"); } }
namespace MvcTest { public class Startup { public void ConfigureServices(IServiceCollection services) { // ... services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddRouting(option => { option.ConstraintMap.Add(key: "transformer1", value: typeof(CustomUrlTransformer)); option.LowercaseUrls = true; }); }
namespace MvcTest { public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller:transformer1}/{action:transformer1}/{id?}", defaults: new { controller = "Home", action = "Index" } ); }); }
app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller:transformer1=Home}/{action:transformer1=Index}/{id?}" ); });
https://localhost:5001/home/view-details
> ng new angular-template-driven-forms-lab --routing
> npm install bootstrap --save
"apps": [ { "styles": [ "../node_modules/bootstrap/dist/css/bootstrap.min.css", "styles.css" ],
>ng g c welcome >ng g c PageNotFound
@NgModule({ declarations: [ AppComponent, WelcomeComponent, PageNotFoundComponent ],
import { PageNotFoundComponent } from './page-not-found/page-not-found.component'; import { WelcomeComponent } from './welcome/welcome.component'; import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: 'welcome', component: WelcomeComponent }, { path: '', redirectTo: 'welcome', pathMatch: 'full' }, { path: '**', component: PageNotFoundComponent } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
<nav class="navbar navbar-default"> <div class="container-fluid"> <a class="navbar-brand">{{title}}</a> <ul class="nav navbar-nav"> <li> <a [routerLink]="['/']">Home</a> </li> </ul> </div> </nav> <div class="container"> <router-outlet></router-outlet> </div>
import { FormsModule } from '@angular/forms'; @NgModule({ imports: [ BrowserModule, FormsModule, AppRoutingModule ]
>ng g m Employee -m app.module --routing
installing module create src\app\employee\employee-routing.module.ts create src\app\employee\employee.module.ts update src\app\app.module.ts
import { EmployeeRoutingModule } from './employee/employee-routing.module'; @NgModule({ imports: [ BrowserModule, FormsModule, AppRoutingModule, EmployeeRoutingModule ]
import { EmployeeModule } from './employee/employee.module'; @NgModule({ imports: [ BrowserModule, FormsModule, EmployeeModule, AppRoutingModule ]
>ng g c employee/employee-register
installing component create src\app\employee\employee-register\employee-register.component.css create src\app\employee\employee-register\employee-register.component.html create src\app\employee\employee-register\employee-register.component.spec.ts create src\app\employee\employee-register\employee-register.component.ts update src\app\employee\employee.module.ts
import { EmployeeRegisterComponent } from './employee-register/employee-register.component'; @NgModule({ declarations: [EmployeeRegisterComponent]
import { EmployeeRegisterComponent } from './employee-register/employee-register.component'; const routes: Routes = [ { path: 'register', component: EmployeeRegisterComponent } ];
<ul class="nav navbar-nav"> <li> <a [routerLink]="['/']">Home</a> </li> <li> <a [routerLink]="['/register']">Register</a> </li> </ul>
// todo: change `imageName` according to the form's file element name
[HttpPost] public ActionResult UploadFiles(HttpPostedFileBase xThumbnail, int id) {
<input type="button" onclick="startTrace('Some Text')" value="startTrace" /> <input type="button" onclick="startError()" value="test Error" /> <script type="text/javascript"> function startTrace(str) { return method1(100, 200); } function method1(arg1, arg2) { return method2(arg1 + arg2 + 100); } function method2(arg1) { var var1 = arg1 / 100; return method3(var1); } function method3(arg1) { console.trace(); var total = arg1 * 100; return total; } function testCount() { // do something console.count("testCount() Calls Count ."); } function startError() { testError(); } function testError() { var errorObj = new Error(); errorObj.message = "this is a test error"; console.exception(errorObj); } function testFunc() { var t = 0; for (var i = 0; i < 100; i++) { t += i; } } </script>
console.log("This is a log message!");
console.log(1 , "+" , 2 , "=", (1+2));
مثال :
console.log("Firebug 1.0 beta was %s in December %i.","released",2006);
console.log("this is a test functin : %o",testFunc);
نتیجه :
console.log("this is a test functin : %s",testFunc);
توسط جایگزین %c هم میتوانید خروجی را فرمت کنید .
console.log("%cThis is a Style Formatted Log","color:green;text-decoration:underline;");
نتیجه :
console.assert(1==1,"this is a test error"); console.assert(1!=1,"this is a test error");
نتیجه :
console.group("Group1"); console.log("Log in Group1"); console.group("Group2"); console.log("Log in Group2"); console.group("Group3"); console.log("Log in Group3");
console.time("TestTime"); var t = 1; for (var i = 0; i < 100000; i++) { t *= (i + t) } console.timeEnd("TestTime");
startError();
برای اطلاعات بیشتر به اینجا مراجعه کنید .
namespace Loans.Entities { public class Applicant { public int Id { set; get; } public string Name { set; get; } public int Age { set; get; } public string Address { set; get; } public decimal Salary { set; get; } } }
namespace Loans.Entities { public class LoanProduct { public int Id { set; get; } public string ProductName { set; get; } public decimal InterestRate { set; get; } } }
namespace Loans.Entities { public class LoanApplication { public int Id { set; get; } public LoanProduct Product { set; get; } public LoanAmount Amount { set; get; } public Applicant Applicant { set; get; } public bool IsAccepted { set; get; } } public class LoanAmount { public string CurrencyCode { get; set; } public decimal Principal { get; set; } } }
namespace Loans.Models { public class IdentityVerificationStatus { public bool Passed { get; set; } } }
using Loans.Models; namespace Loans.Services.Contracts { public interface IIdentityVerifier { void Initialize(); bool Validate(string applicantName, int applicantAge, string applicantAddress); void Validate(string applicantName, int applicantAge, string applicantAddress, out bool isValid); void Validate(string applicantName, int applicantAge, string applicantAddress, ref IdentityVerificationStatus status); } }
namespace Loans.Services.Contracts { public interface ICreditScorer { int Score { get; } void CalculateScore(string applicantName, string applicantAddress); } }
using System; using Loans.Entities; using Loans.Services.Contracts; namespace Loans.Services { public class LoanApplicationProcessor { private const decimal MinimumSalary = 1_500_000_0; private const int MinimumAge = 18; private const int MinimumCreditScore = 100_000; private readonly IIdentityVerifier _identityVerifier; private readonly ICreditScorer _creditScorer; public LoanApplicationProcessor( IIdentityVerifier identityVerifier, ICreditScorer creditScorer) { _identityVerifier = identityVerifier ?? throw new ArgumentNullException(nameof(identityVerifier)); _creditScorer = creditScorer ?? throw new ArgumentNullException(nameof(creditScorer)); } public bool Process(LoanApplication application) { application.IsAccepted = false; if (application.Applicant.Salary < MinimumSalary) { return application.IsAccepted; } if (application.Applicant.Age < MinimumAge) { return application.IsAccepted; } _identityVerifier.Initialize(); var isValidIdentity = _identityVerifier.Validate( application.Applicant.Name, application.Applicant.Age, application.Applicant.Address); if (!isValidIdentity) { return application.IsAccepted; } _creditScorer.CalculateScore(application.Applicant.Name, application.Applicant.Address); if (_creditScorer.Score < MinimumCreditScore) { return application.IsAccepted; } application.IsAccepted = true; return application.IsAccepted; } } }
using System; using Loans.Models; using Loans.Services.Contracts; namespace Loans.Services { public class IdentityVerifierServiceGateway : IIdentityVerifier { public DateTime LastCheckTime { get; private set; } public void Initialize() { // Initialize connection to external service } public bool Validate(string applicantName, int applicantAge, string applicantAddress) { Connect(); var isValidIdentity = CallService(applicantName, applicantAge, applicantAddress); LastCheckTime = DateTime.Now; Disconnect(); return isValidIdentity; } private void Connect() { // Open connection to external service } private bool CallService(string applicantName, int applicantAge, string applicantAddress) { // Make call to external service, interpret the response, and return result return false; // Simulate result for demo purposes } private void Disconnect() { // Close connection to external service } public void Validate(string applicantName, int applicantAge, string applicantAddress, out bool isValid) { throw new NotImplementedException(); } public void Validate(string applicantName, int applicantAge, string applicantAddress, ref IdentityVerificationStatus status) { throw new NotImplementedException(); } } }
public LoanApplicationProcessor( IIdentityVerifier identityVerifier, ICreditScorer creditScorer) { _identityVerifier = identityVerifier ?? throw new ArgumentNullException(nameof(identityVerifier)); _creditScorer = creditScorer ?? throw new ArgumentNullException(nameof(creditScorer)); }
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>netcoreapp2.2</TargetFramework> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\Loans\Loans.csproj" /> </ItemGroup> <ItemGroup> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.3.0" /> <PackageReference Include="MSTest.TestAdapter" Version="2.0.0" /> <PackageReference Include="MSTest.TestFramework" Version="2.0.0" /> </ItemGroup> </Project>
using Loans.Entities; using Loans.Services; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Loans.Tests { [TestClass] public class LoanApplicationProcessorShould { [TestMethod] public void DeclineLowSalary() { var product = new LoanProduct {Id = 99, ProductName = "Loan", InterestRate = 5.25m}; var amount = new LoanAmount {CurrencyCode = "Rial", Principal = 2_000_000_0}; var applicant = new Applicant {Id = 1, Name = "User 1", Age = 25, Address = "This place", Salary = 1_100_000_0}; var application = new LoanApplication {Id = 42, Product = product, Amount = amount, Applicant = applicant}; var processor = new LoanApplicationProcessor(null, null); processor.Process(application); Assert.IsFalse(application.IsAccepted); } } }
public class LoanApplicationProcessor { private const decimal MinimumSalary = 1_500_000_0;
Test method Loans.Tests.LoanApplicationProcessorShould.DeclineLowSalary threw exception: System.ArgumentNullException: Value cannot be null. Parameter name: identityVerifier
public LoanApplicationProcessor( IIdentityVerifier identityVerifier, ICreditScorer creditScorer) { _identityVerifier = identityVerifier ?? throw new ArgumentNullException(nameof(identityVerifier)); _creditScorer = creditScorer ?? throw new ArgumentNullException(nameof(creditScorer)); }
> dotnet add package Moq > Install-Package Moq
using Loans.Entities; using Loans.Services; using Loans.Services.Contracts; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; namespace Loans.Tests { [TestClass] public class LoanApplicationProcessorShould { [TestMethod] public void DeclineLowSalary() { var product = new LoanProduct {Id = 99, ProductName = "Loan", InterestRate = 5.25m}; var amount = new LoanAmount {CurrencyCode = "Rial", Principal = 2_000_000_0}; var applicant = new Applicant {Id = 1, Name = "User 1", Age = 25, Address = "This place", Salary = 1_100_000_0}; var application = new LoanApplication {Id = 42, Product = product, Amount = amount, Applicant = applicant}; var mockIdentityVerifier = new Mock<IIdentityVerifier>(); var mockCreditScorer = new Mock<ICreditScorer>(); var processor = new LoanApplicationProcessor(mockIdentityVerifier.Object, mockCreditScorer.Object); processor.Process(application); Assert.IsFalse(application.IsAccepted); } } }
using Loans.Entities; using Loans.Services; using Loans.Services.Contracts; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; namespace Loans.Tests { [TestClass] public class LoanApplicationProcessorShould { [TestMethod] public void Accept() { var product = new LoanProduct {Id = 99, ProductName = "Loan", InterestRate = 5.25m}; var amount = new LoanAmount {CurrencyCode = "Rial", Principal = 2_000_000_0}; var applicant = new Applicant {Id = 1, Name = "User 1", Age = 25, Address = "This place", Salary = 1_500_000_0}; var application = new LoanApplication {Id = 42, Product = product, Amount = amount, Applicant = applicant}; var mockIdentityVerifier = new Mock<IIdentityVerifier>(); var mockCreditScorer = new Mock<ICreditScorer>(); var processor = new LoanApplicationProcessor(mockIdentityVerifier.Object, mockCreditScorer.Object); processor.Process(application); Assert.IsTrue(application.IsAccepted); } } }
_identityVerifier.Initialize(); var isValidIdentity = _identityVerifier.Validate( application.Applicant.Name, application.Applicant.Age, application.Applicant.Address);
public class HackWindowsForms { struct POINTAPI { public int X; public int Y; } [DllImport("user32.dll")] static extern int EnumChildWindows(int hWndParent, EnumChildCallbackDelegate enumChildCallback, int lParam); [DllImport("user32.dll")] static extern int EnableWindow(int hwnd, int fEnable); [DllImport("user32.dll")] static extern int WindowFromPoint(int x, int y); [DllImport("user32.dll")] static unsafe extern int GetCursorPos(POINTAPI* lpPoint); delegate int EnumChildCallbackDelegate(int hwnd, int lParam); public static void EnableThisWindowControls() { unsafe { POINTAPI cursorPosition = new POINTAPI(); GetCursorPos(&cursorPosition); int winWnd = WindowFromPoint(cursorPosition.X, cursorPosition.Y); EnumChildWindows(winWnd, EnumChildCallback, 0); } } static int EnumChildCallback(int hwnd, int lParam) { EnableWindow(hwnd, 1); EnumChildWindows(hwnd, EnumChildCallback, 0); return 1; } }
private void button1_MouseUp(object sender, MouseEventArgs e) { HackWindowsForms.EnableThisWindowControls(); MessageBox.Show("حالا روی دکمه مورد نظر کلیک کنید و کلید space را فشار دهید.", "", MessageBoxButtons.OK, MessageBoxIcon.Asterisk, MessageBoxDefaultButton.Button1, MessageBoxOptions.RtlReading); }
public class Student { public int Id { get; set; } public string Name { get; set; } public string Family { get; set; } public DateTime Birthdate { get; set; } public string Tel { get; set; } public string CellPhone { get; set; } [Email] public string Email { get; set; } }
public class StudentViewModel { public string Name { get; set; } public string Family { get; set; } public string Email { get; set; } }
public ActionResult Index() { var model = db.Students.ToList(); AutoMapper.Mapper.CreateMap<Student,StudentViewModel>(); var studentViewModel = AutoMapper.Mapper.Map<List<Student>, IEnumerable<StudentViewModel>>(model); return View(studentViewModel); }
AutoMapper.Mapper.CreateMap<Student,StudentViewModel>();
An exception of type 'AutoMapper.AutoMapperMappingException' occurred in AutoMapper.dll but was not handled in user code
در واقع ما یک سیستمی داریم که شامل مدلی است از دیتاهای ما و از این مدل برای کوئری گرفتن از دیتابیس استفاده میشود، که البته برای بیشتر پروژههای نرم افزاری، معماری درست و ترجیح داده شدهای هم میباشد.
زمانیکه نیازهای پروژه روز به روز افزورده و پیچیدهتر میشود، مدل CRUD بصورت پیوسته از ارزشش کاسته میشود و از آن سادگی اولیهی در درک و خوانایی آن دور خواهد شد.
ذات CQRS بر آن است که شما مدلهای مختلفی را برای خواندن و نوشتن دیتا داشته باشید. الگوی آن چیزی شبیه به تصویر زیر است
ES از برنامه نویسان میخواهد که مدل سنتی CRUD را فراموش کرده و بجای آن تغییراتی را که روی دیتا صورت گرفته، نیز درج نمایند. اینکار به وسیلهی یک دیتابیس Append-only انجام میشود که به نام Event Store شناخته میشود.
در این معماری ما همهی تغییرات روی دیتا را به صورت Serialize Event ذخیره میکنیم که میتواند دوباره در هر زمانی اجرا شده و current state هر objectی را در اختیار بگذارد.
این روش به ما کمک بزرگی میکند تا وضعیت یک object را در گذشته به راحتی پیدا کنیم و از آن میتوان به غیر از فوایدی که دارد، به عنوان یک Logger نیز استفاده نمود. به دلیل اینکه جزء به جزء تغییرات بر روی state سیستم، در آن ثبت شده است. از آنجاییکه دیتا بصورت serialize ذخیره میشود، بارگزاری آن نیز با سرعت بالایی انجام خواهد شد.
public class Movie : AggregateRoot { public string Title { get; set; } public DateTime ReleaseDate { get; set; } public int RunningTimeMinutes { get; set; } public Movie() { } public Movie(Guid movieId, string title, DateTime releaseDate, int runningTimeMinutes) { //پیاده سازی خواهد شد } }
public class CreateMovieCommand : ICommand { public string Title { get; set; } public DateTime ReleaseDate { get; set; } public int RunningTimeMinutes { get; set; } public CreateMovieCommand(string title, DateTime releaseDate, int runningTime) { Title = title; ReleaseDate = releaseDate; RunningTimeMinutes = runningTime; } }
public class CreateMovieCommandHandler : CommandHandler<CreateMovieCommand> { protected IDomainRepository _repository; public CreateMovieCommandHandler(IDomainRepository repository) { _repository = repository; } public override void Handle(CreateMovieCommand command) { var movie = new Domain.Movie(Guid.NewGuid(), command.Title, command.ReleaseDate, command.RunningTimeMinutes); _repository.Save(movie); } }
public class MovieCreatedEvent : DomainEvent { public Guid MovieId { get { return AggregateRootId; } set { AggregateRootId = value;} } public string Title { get; set; } public DateTime ReleaseDate { get; set; } public int RunningTimeMinutes { get; set; } public MovieCreatedEvent(Guid movieId, string title, DateTime releaseDate, int runningTime) { MovieId = movieId; Title = title; ReleaseDate = releaseDate; RunningTimeMinutes = runningTime; } }
public class Movie : AggregateRoot { public string Title { get; set; } public DateTime ReleaseDate { get; set; } public int RunningTimeMinutes { get; set; } public Movie(Guid movieId, string title, DateTime releaseDate, int runningTimeMinutes) { Apply(new MovieCreatedEvent(Guid.NewGuid(), title, releaseDate, runningTimeMinutes)); } }
public class MovieEventHandler : IHandleDomainEvents<MovieCreatedEvent> { public void Handle(MovieCreatedEvent createdEvent) { using (MoviesContext entities = new MoviesContext()) { entities.Movies.Add(new Movie() { Id = createdEvent.AggregateRootId, Title = createdEvent.Title, ReleaseDate = createdEvent.ReleaseDate, RunningTimeMinutes = createdEvent.RunningTimeMinutes }); entities.SaveChanges(); } } }
protected void OnMovieCreated(MovieCreatedEvent domainEvent) { Id = domainEvent.AggregateRootId; Title = domainEvent.Title; ReleaseDate = domainEvent.ReleaseDate; RunningTimeMinutes = domainEvent.RunningTimeMinutes; }
<Window> <Grid> <Label Content="Label" /> <Button Content="Button" /> </Grid> </Window>
جادوی پشت صحنه
مقادیر پراپرتیها در کلاسی استاتیک به اسم Dependency Property ذخیره میشوند که این ذخیره در حالت نام و مقدار است و مقدار آن شامل callback و مقدار پیش فرض است. شکل زیر نتیجهی شکل دقیقتری را نسبت به قبلی در هنگام پیمایش درخت منطقی به سمت بالا، نشان میدهد.
نحوهی تعریف یک خاصیت وابسته که باید به صورت ایستا تعریف شود به صورت زیر است و برای دریافت و درج مقدار جدید از یک پراپرتی معمولی کمک میگیریم:
// Dependency Property public static readonly DependencyProperty CurrentTimeProperty = DependencyProperty.Register( "CurrentTime", typeof(DateTime), typeof(MyClockControl), new FrameworkPropertyMetadata(DateTime.Now)); // .NET Property wrapper public DateTime CurrentTime { get { return (DateTime)GetValue(CurrentTimeProperty); } set { SetValue(CurrentTimeProperty, value); } }