This chapter describes the backward-compatibility features of Punch to help with migration of an existing code base.
One of the bigger breaking changes in Punch and DevForce 2012 is the drop of the Coroutine-style Asynchronous Pattern in favor of the more modern Task-based Asynchronous Pattern (TAP). To ease migration of legacy code to TAP, both DevForce and Punch provide Compatibility Packs with limited backwards-compatibility for the Coroutine-style Asynchronous Pattern.
To add backwards-compatibility support to your projects, install the "Punch Compatibility Pack NuGet package to each project, this will add a reference to Cocktail.Compat.dll. In addition, the "DevForce 2012 Compatibility Pack is automatically installed as a required dependency, which adds a reference to IdeaBlade.EntityModel.Compat.dll.
The "Punch Compatibility Pack" provides the following features.
In many cases, OperationResult and Task can be used interchangeably. The compiler implicitly converts one to the other if possible. Consider the following example.
C# | public OperationResult<bool> SomeMethodAsync() { return OperationResult.FromResult(true); } public Task<bool> SomeMethodTaskAsync() { // Implicit conversion from OperationResult<bool> to Task<bool> return SomeMethodAsync(); } |
Similarly, OperationResult can be awaited in an asynchronous method as demonstrated in the following example.
C# | public OperationResult<bool> SomeMethodAsync() { return OperationResult.FromResult(true); } public async Task<bool> SomeMethodTaskAsync() { // Await OperationResult<bool> and return result value. return await SomeMethodAsync(); } |
The opposite is true as well as demonstrated in the following example.
C# | public OperationResult<bool> SomeMethodAsync() { // Implicit conversion from Task<bool> to OperationResult<bool> return SomeMethodTaskAsync(); } public Task<bool> SomeMethodTaskAsync() { return Task.FromResult(true); } |
In cases where the compiler cannot implicitly convert between OperationResult and Task, we can help it along with explicit conversions as demonstrated in the following example.
C# | public Task<bool> SomeMethodAsync() { return Task.FromResult(true); } public OperationResult LegacyCoroutine() { return Coroutine.Start(LegacyCoroutineCore).AsOperationResult(); } public IEnumerable<INotifyCompleted> LegacyCoroutineCore() { // Explicit conversion to OperationResult<bool> required yield return SomeMethodAsync().AsOperationResult(); } |
Last but not least, both the "Punch Compatibility Pack" and "DevForce Compatibility Pack" provide a series of extension methods with backwards-compatible method signatures. Despite these extension methods, minor code changes are unavoidable. In order to disambiguate the legacy methods from the TAP methods, certain parameters that used to be optional are no longer optional and must be provided with a value or null.
Consider the following example.
C# | public IEnumerable<INotifyCompleted> UpdateCompanyName() { var provider = new EntityManagerProvider<EntityManager>(); var uow = new UnitOfWork<Customer>(provider); // Retrieve customer var id = new Guid( "ed99343d-b368-4007-90a2-48ccf2699d44"); OperationResult<Customer> operation; yield return operation = uow.Entities.WithIdAsync(id); // Implicit conversion to OperationResult<Customer> // Update company name operation.Result.CompanyName = "Test" ; // Commit changes, using legacy extension method instead of explicit conversion // yield return uow.CommitAsync().AsOperationResult(); yield return uow.CommitAsync(null, null); } |
As with OperationResult, the "Punch Compatiblity Pack" enables await for DevForce legacy operations as demonstrated in the following example.
C# | // Legacy method returning DevForce EntityQueryOperation from IdeaBlade.EntityModel.Compat private EntityQueryOperation<Customer> GetCustomersAsync() { var query = new EntityManager().GetQuery<Customer>(); return query.ExecuteAsync(null); } public async Task<IEnumerable<Customer>> GetCustomersTaskAsync() { return await GetCustomersAsync(); } |
The following enhancements require code changes when migrating from Cocktail 2010 to Punch.