Open sandboxFocusImprove this doc

Migrating custom aspects to Metalama

Step 0. Learn Metalama on some sandbox project

Before porting your PostSharp aspects to Metalama, familiarize yourself with the new product by using it in a new project. Ideally, write a prototype of aspects in a sandbox project without PostSharp. It's important to note that while migrating aspects, you may not be able to run your application or all your unit tests. Therefore, learning in a sandbox project is advisable.

Step 1. Create a list of aspects and assess their importance

First, identify all used aspects across all projects.

Next, assess the importance of these aspects:

  1. Aspects required for unit tests to succeed,
  2. Aspects required for the application to run,
  3. Aspects required in production but not in a development environment, such as logging, profiling, or caching.

After assessing, sort the aspects by importance. This list will guide you on how to implement the aspects.

Identify uses of multicasting

Determine if attribute multicasting is used for each aspect, and how it's used. All PostSharp aspects implicitly inherit from the MulticastAttribute, meaning all aspects can be multicast, but not all necessarily are. To identify which aspects use the multicasting feature, perform a "Find in Files" for the following substrings: AttributeTarget or AttributeExclude.

If an aspect is multicast only from assembly-level custom attributes, it doesn't imply that your Metalama aspect will have to implement multicasting. In fact, using fabrics is a more elegant approach than assembly-level multicasting. See Fabrics for details. However, if the source code uses multicasting from classes or structs, your Metalama aspect must implement multicasting.

Step 2. Verify that it's a good time to migrate

Refer to When to migrate from PostSharp to Metalama and ensure that Metalama supports the target frameworks of your projects. Unless the projects still target obsolete platforms, they are likely to be supported.

Check Status of the migration of PostSharp features to Metalama to see if your projects use a feature of PostSharp that hasn't been ported to Metalama yet. If your project uses ready-made aspects from the PostSharp.Patterns namespace, verify that these aspects have been ported.

Step 3. Verify that your projects are in a clean state

Before starting the migration, ensure that your projects are in a clean state:

  • Create a new branch for this task in your source repository.
  • Ensure that the projects build without error. If possible, resolve any warnings in your code.
  • Confirm that all unit tests are successful.
  • Once your projects are free of errors, warnings, and failed tests, commit and push your branch.

Step 4. Change PostSharp package references to Metalama.Migration and check errors

Replace all references to the PostSharp package with references to the Metalama.Migration package across all projects. This can likely be done with a "Replace in Files" operation. However, if you use packages.config, consider migrating your projects to the new PackageReference format. If you can't, use the NuGet Package Manager UI to uninstall the PostSharp package and install the Metalama.Migration package.

The Metalama.Migration package contains the public API of PostSharp, but not its implementation. Instead, it contains [Obsolete] annotations with indications about the equivalent class or method in Metalama.

Building these projects at this point will likely result in numerous warnings.

If your code uses APIs that haven't been ported to PostSharp, you may also encounter errors. If you see errors, consider possible workarounds. If none are available, you may need to delay the migration effort.

Do not attempt to run your application or your unit tests at this point. They won't function until you port all critical aspects.

Step 5. Create a separate project for aspect tests

Since your current test base will likely be disrupted for a while — until all your critical aspects have been ported — it's a good idea to set up an infrastructure where you can test your aspects individually.

For more details, see Testing the aspect's code generation and error reporting.

Step 6. Implement the individual aspects

Using the list you created in step 1, start with the most essential aspects.

Metalama is not just an update of PostSharp; it has a completely different architecture and approach. Consequently, you will need to rewrite each aspect from scratch.

To determine the Metalama equivalent of any PostSharp API, refer to the [Obsolete] warnings reported by the Metalama.Migration package on your code. We haven't included a tutorial on porting a specific aspect to Metalama here because, if you've completed Step 0 as suggested, you should already be familiar with this process. As mentioned earlier, it is beneficial to learn Metalama before undertaking the actual migration work.

We strongly recommend writing aspect tests for each aspect you are implementing.

If you identified in Step 1 that the aspect should support multicasting, refer to Migrating PostSharp attribute multicasting to Metalama.

Step 7. Migrate usages of multicasting

The best way to migrate assembly multicasting is to use a project fabric as described in Adding many aspects simultaneously.

For type-level multicasting, if you have built multicasting into your Metalama aspects as described in Migrating PostSharp attribute multicasting to Metalama, replacing the namespace PostSharp.Extensibility with Metalama.Extensions.Multicast using a "Replace in Files" operation should suffice.

Step 8. Migrate configuration

If you have configuration or multicasting in a PostSharp file like postsharp.config or MyProject.psproj, they should be migrated to project fabrics as described in Configuring aspects with fabrics.

For more details, see Migrating PostSharp configuration to Metalama.

Step 9. Last project clean up

At this point, we recommend addressing all warnings.

If your Metalama aspects have been correctly implemented, all your tests should now pass and the application should run as before.

Once this is the case, replace the reference to the Metalama.Migration package with Metalama.Framework.

You have now completed the migration.