diff --git a/examples/dapr/CommunityToolkit.Aspire.Hosting.Dapr.AppHost/Program.cs b/examples/dapr/CommunityToolkit.Aspire.Hosting.Dapr.AppHost/Program.cs
index 981f5e980..847c9aaec 100644
--- a/examples/dapr/CommunityToolkit.Aspire.Hosting.Dapr.AppHost/Program.cs
+++ b/examples/dapr/CommunityToolkit.Aspire.Hosting.Dapr.AppHost/Program.cs
@@ -3,27 +3,37 @@
 var redis = builder.AddRedis("redis").WithRedisInsight();
 
 
-var stateStore = builder.AddDaprStateStore("statestore");
-
-var pubSub = builder.AddDaprPubSub("pubsub")
-                    .WithMetadata("redisHost", "localhost:6379")
-                    .WaitFor(redis);
+var stateStore = builder.AddDaprStateStore("statestore")
+    .WaitFor(redis);
+
+var redisHost= redis.Resource.PrimaryEndpoint.Property(EndpointProperty.Host);
+var redisTargetPort = redis.Resource.PrimaryEndpoint.Property(EndpointProperty.TargetPort);
+
+var pubSub = builder
+  .AddDaprPubSub("pubsub")
+  .WithMetadata(
+    "redisHost",
+    ReferenceExpression.Create(
+      $"{redisHost}:{redisTargetPort}"
+    )
+  )
+  .WaitFor(redis);
 
 builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("servicea")
        .WithReference(stateStore)
        .WithReference(pubSub)
        .WithDaprSidecar()
-       .WaitFor(redis);
+       .WaitFor(pubSub);
 
 builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceB>("serviceb")
        .WithReference(pubSub)
        .WithDaprSidecar()
-       .WaitFor(redis);
+       .WaitFor(pubSub);
 
 // console app with no appPort (sender only)
 builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceC>("servicec")
        .WithReference(stateStore)
        .WithDaprSidecar()
-       .WaitFor(redis);
+       .WaitFor(stateStore);
 
 builder.Build().Run();
diff --git a/src/Shared/Dapr/Core/DaprComponentMetadataAnnotation.cs b/src/Shared/Dapr/Core/DaprComponentMetadataAnnotation.cs
index 7edadc557..403e09f9b 100644
--- a/src/Shared/Dapr/Core/DaprComponentMetadataAnnotation.cs
+++ b/src/Shared/Dapr/Core/DaprComponentMetadataAnnotation.cs
@@ -1,4 +1,4 @@
 ﻿using Aspire.Hosting.ApplicationModel;
 
 namespace CommunityToolkit.Aspire.Hosting.Dapr;
-internal sealed record DaprComponentConfigurationAnnotation(Func<DaprComponentSchema, Task> Configure) : IResourceAnnotation;
+internal sealed record DaprComponentConfigurationAnnotation(Func<DaprComponentSchema, CancellationToken, Task> Configure) : IResourceAnnotation;
diff --git a/src/Shared/Dapr/Core/DaprComponentSchema.cs b/src/Shared/Dapr/Core/DaprComponentSchema.cs
index 72aec7e65..9e0972b65 100644
--- a/src/Shared/Dapr/Core/DaprComponentSchema.cs
+++ b/src/Shared/Dapr/Core/DaprComponentSchema.cs
@@ -1,4 +1,5 @@
-﻿using YamlDotNet.Serialization;
+﻿using Aspire.Hosting.ApplicationModel;
+using YamlDotNet.Serialization;
 using YamlDotNet.Serialization.NamingConventions;
 
 namespace CommunityToolkit.Aspire.Hosting.Dapr;
@@ -29,6 +30,20 @@ public DaprComponentSchema(string name, string type)
         };
     }
     public override string ToString() => serializer.Serialize(this);
+    
+    /// <summary>
+    /// Resolves all async values in the component schema
+    /// </summary>
+    public async Task ResolveAllValuesAsync(CancellationToken cancellationToken = default)
+    {
+        foreach (var metadata in Spec.Metadata)
+        {
+            if (metadata is DaprComponentSpecMetadataValueProvider valueProvider)
+            {
+                await valueProvider.ResolveValueAsync(cancellationToken);
+            }
+        }
+    }
 
     public static DaprComponentSchema FromYaml(string yamlContent) =>
         deserializer.Deserialize<DaprComponentSchema>(yamlContent);
@@ -104,6 +119,29 @@ public sealed class DaprComponentSpecMetadataValue : DaprComponentSpecMetadata
     public required string Value { get; set; }
 }
 
+internal sealed class DaprComponentSpecMetadataValueProvider : DaprComponentSpecMetadata
+{
+    /// <summary>
+    /// The value provider for deferred evaluation
+    /// </summary>
+    [YamlIgnore]
+    public required IValueProvider ValueProvider { get; init; }
+    
+    /// <summary>
+    /// The resolved value (populated after resolution)
+    /// </summary>
+    [YamlMember(Order = 2)]
+    public string? Value { get; set; }
+    
+    /// <summary>
+    /// Resolves the value from the provider
+    /// </summary>
+    public async Task ResolveValueAsync(CancellationToken cancellationToken = default)
+    {
+        Value = await ValueProvider.GetValueAsync(cancellationToken) ?? string.Empty;
+    }
+}
+
 /// <summary>
 /// Represents a Dapr component spec metadata item with a secret key reference
 /// </summary>
diff --git a/src/Shared/Dapr/Core/DaprComponentValueProviderAnnotation.cs b/src/Shared/Dapr/Core/DaprComponentValueProviderAnnotation.cs
new file mode 100644
index 000000000..bece8f296
--- /dev/null
+++ b/src/Shared/Dapr/Core/DaprComponentValueProviderAnnotation.cs
@@ -0,0 +1,8 @@
+using Aspire.Hosting.ApplicationModel;
+
+namespace CommunityToolkit.Aspire.Hosting.Dapr;
+
+/// <summary>
+/// Annotation that tracks value providers that need deferred resolution for Dapr component metadata
+/// </summary>
+internal sealed record DaprComponentValueProviderAnnotation(string MetadataName, string EnvironmentVariableName, IValueProvider ValueProvider) : IResourceAnnotation;
\ No newline at end of file
diff --git a/src/Shared/Dapr/Core/DaprDistributedApplicationLifecycleHook.cs b/src/Shared/Dapr/Core/DaprDistributedApplicationLifecycleHook.cs
index c42ae6727..0a18e487a 100644
--- a/src/Shared/Dapr/Core/DaprDistributedApplicationLifecycleHook.cs
+++ b/src/Shared/Dapr/Core/DaprDistributedApplicationLifecycleHook.cs
@@ -3,9 +3,11 @@
 
 using Aspire.Hosting;
 using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.Eventing;
 using Aspire.Hosting.Lifecycle;
 using Aspire.Hosting.Utils;
 using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Hosting;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
@@ -32,6 +34,10 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell
     {
         string appHostDirectory = GetAppHostDirectory();
 
+        // Set up WaitAnnotations for Dapr components based on their value provider dependencies
+        SetupComponentLifecycle(appModel);
+
+
         var onDemandResourcesPaths = await StartOnDemandDaprComponentsAsync(appModel, cancellationToken).ConfigureAwait(false);
 
         var sideCars = new List<ExecutableResource>();
@@ -71,12 +77,22 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell
 
             var componentReferenceAnnotations = resource.Annotations.OfType<DaprComponentReferenceAnnotation>();
 
-            var waitAnnotationsToCopyToDaprCli = new List<WaitAnnotation>();
-
             var secrets = new Dictionary<string, string>();
+            var endpointEnvironmentVars = new Dictionary<string, IValueProvider>();
+            var hasValueProviders = false;
 
             foreach (var componentReferenceAnnotation in componentReferenceAnnotations)
             {
+                // Check if there are any value provider references that need to be added as environment variables
+                if (componentReferenceAnnotation.Component.TryGetAnnotationsOfType<DaprComponentValueProviderAnnotation>(out var endpointAnnotations))
+                {
+                    foreach (var endpointAnnotation in endpointAnnotations)
+                    {
+                        endpointEnvironmentVars[endpointAnnotation.EnvironmentVariableName] = endpointAnnotation.ValueProvider;
+                        hasValueProviders = true;
+                    }
+                }
+                
                 // Check if there are any secrets that need to be added to the secret store
                 if (componentReferenceAnnotation.Component.TryGetAnnotationsOfType<DaprComponentSecretAnnotation>(out var secretAnnotations))
                 {
@@ -84,22 +100,18 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell
                     {
                         secrets[secretAnnotation.Key] = (await secretAnnotation.Value.GetValueAsync(cancellationToken))!;
                     }
-                    // We need to append the secret store path to the resources path
-                    onDemandResourcesPaths.TryGetValue("secretstore", out var secretStorePath);
+                }
+                
+                // If we have any secrets or value providers, ensure the secret store path is added
+                if ((secrets.Count > 0 || hasValueProviders) && onDemandResourcesPaths.TryGetValue("secretstore", out var secretStorePath))
+                {
                     string onDemandResourcesPathDirectory = Path.GetDirectoryName(secretStorePath)!;
-
                     if (onDemandResourcesPathDirectory is not null)
                     {
                         aggregateResourcesPaths.Add(onDemandResourcesPathDirectory);
                     }
                 }
 
-                // Whilst we are passing over each component annotations collect the list of annotations to copy to the Dapr CLI.
-                if (componentReferenceAnnotation.Component.TryGetAnnotationsOfType<WaitAnnotation>(out var componentWaitAnnotations))
-                {
-                    waitAnnotationsToCopyToDaprCli.AddRange(componentWaitAnnotations);
-                }
-
                 if (componentReferenceAnnotation.Component.Options?.LocalPath is not null)
                 {
                     var localPathDirectory = Path.GetDirectoryName(NormalizePath(componentReferenceAnnotation.Component.Options.LocalPath));
@@ -120,19 +132,23 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell
                 }
             }
 
-            if (secrets.Count > 0)
+            if (secrets.Count > 0 || endpointEnvironmentVars.Count > 0)
             {
-                daprSidecar.Annotations.Add(new EnvironmentCallbackAnnotation(context =>
+                daprSidecar.Annotations.Add(new EnvironmentCallbackAnnotation(async context =>
                 {
                     foreach (var secret in secrets)
                     {
                         context.EnvironmentVariables.TryAdd(secret.Key, secret.Value);
                     }
-
+                    
+                    // Add value provider references
+                    foreach (var (envVarName, valueProvider) in endpointEnvironmentVars)
+                    {
+                        var value = await valueProvider.GetValueAsync(context.CancellationToken);
+                        context.EnvironmentVariables.TryAdd(envVarName, value ?? string.Empty);
+                    }
                 }));
             }
-            // It is possible that we have duplicate wate annotations so we just dedupe them here.
-            var distinctWaitAnnotationsToCopyToDaprCli = waitAnnotationsToCopyToDaprCli.DistinctBy(w => (w.Resource, w.WaitType));
 
             var daprAppPortArg = (int? port) => ModelNamedArg("--app-port", port);
             var daprGrpcPortArg = (object port) => ModelNamedObjectArg("--dapr-grpc-port", port);
@@ -183,8 +199,11 @@ public async Task BeforeStartAsync(DistributedApplicationModel appModel, Cancell
             var daprCliResourceName = $"{daprSidecar.Name}-cli";
             var daprCli = new ExecutableResource(daprCliResourceName, fileName, appHostDirectory);
 
-            // Add all the unique wait annotations to the CLI.
-            daprCli.Annotations.AddRange(distinctWaitAnnotationsToCopyToDaprCli);
+            // Make the Dapr CLI wait for the component resources it references
+            foreach (var componentRef in componentReferenceAnnotations)
+            {
+                daprCli.Annotations.Add(new WaitAnnotation(componentRef.Component, WaitType.WaitUntilHealthy));
+            }
 
             resource.Annotations.Add(
                 new EnvironmentCallbackAnnotation(
@@ -416,6 +435,51 @@ static IEnumerable<string> GetAvailablePaths()
         }
     }
 
+    private static void SetupComponentLifecycle(DistributedApplicationModel appModel)
+    {
+        // Setup proper lifecycle for Dapr components with their dependencies
+        // Components will manage their own state and wait for their dependencies
+        foreach (var component in appModel.Resources.OfType<IDaprComponentResource>())
+        {
+            var dependencies = new HashSet<IResource>();
+
+            if (component.TryGetAnnotationsOfType<DaprComponentValueProviderAnnotation>(out var valueProviderAnnotations))
+            {
+                foreach (var annotation in valueProviderAnnotations)
+                {
+                    // Extract resource references from value providers - following the same pattern as SetupSidecarLifecycle
+                    if (annotation.ValueProvider is IResourceWithoutLifetime)
+                    {
+                        // Skip waiting for resources without a lifetime
+                        continue;
+                    }
+
+                    if (annotation.ValueProvider is IResource resource)
+                    {
+                        dependencies.Add(resource);
+                    }
+                    else if (annotation.ValueProvider is IValueWithReferences valueWithReferences)
+                    {
+                        foreach (var innerRef in valueWithReferences.References.OfType<IResource>())
+                        {
+                            if (innerRef is not IResourceWithoutLifetime)
+                            {
+                                dependencies.Add(innerRef);
+                            }
+                        }
+                    }
+                }
+            }
+
+            // Add WaitAnnotations for each unique dependency
+            // This ensures the component waits for its dependencies before becoming ready
+            foreach (var dependency in dependencies)
+            {
+                component.Annotations.Add(new WaitAnnotation(dependency, WaitType.WaitUntilHealthy));
+            }
+        }
+    }
+
     public void Dispose()
     {
         if (_onDemandResourcesRootPath is not null)
@@ -442,8 +506,12 @@ private async Task<IReadOnlyDictionary<string, string>> StartOnDemandDaprCompone
                 .Where(component => component.Options?.LocalPath is null)
                 .ToList();
 
-        // If any of the components have secrets, we will add an on-demand secret store component.
-        if (onDemandComponents.Any(component => component.TryGetAnnotationsOfType<DaprComponentSecretAnnotation>(out var annotations) && annotations.Any()))
+        // If any of the components have secrets or value provider references, we will add an on-demand secret store component.
+        bool needsSecretStore = onDemandComponents.Any(component => 
+            (component.TryGetAnnotationsOfType<DaprComponentSecretAnnotation>(out var secretAnnotations) && secretAnnotations.Any()) ||
+            (component.TryGetAnnotationsOfType<DaprComponentValueProviderAnnotation>(out var valueProviderAnnotations) && valueProviderAnnotations.Any()));
+        
+        if (needsSecretStore)
         {
             onDemandComponents.Add(new DaprComponentResource("secretstore", DaprConstants.BuildingBlocks.SecretStore));
         }
@@ -492,7 +560,7 @@ private async Task<string> GetComponentAsync(DaprComponentResource component, Fu
     {
         // We should try to read content from a known location (such as aspire root directory)
         logger.LogInformation("Unvalidated configuration {specType} for component '{ComponentName}'.", component.Type, component.Name);
-        return await contentWriter(await GetDaprComponent(component, component.Type)).ConfigureAwait(false);
+        return await contentWriter(await GetDaprComponent(component, component.Type, cancellationToken)).ConfigureAwait(false);
     }
     private async Task<string> GetBuildingBlockComponentAsync(DaprComponentResource component, Func<string, Task<string>> contentWriter, string defaultProvider, CancellationToken cancellationToken)
     {
@@ -545,19 +613,21 @@ private static async Task<string> GetDefaultContent(DaprComponentResource compon
         string defaultContent = await File.ReadAllTextAsync(defaultContentPath, cancellationToken).ConfigureAwait(false);
         string yaml = defaultContent.Replace($"name: {component.Type}", $"name: {component.Name}");
         DaprComponentSchema content = DaprComponentSchema.FromYaml(yaml);
-        await ConfigureDaprComponent(component, content);
+        await ConfigureDaprComponent(component, content, cancellationToken);
+        await content.ResolveAllValuesAsync(cancellationToken);
         return content.ToString();
     }
 
 
-    private static async Task<string> GetDaprComponent(DaprComponentResource component, string type)
+    private static async Task<string> GetDaprComponent(DaprComponentResource component, string type, CancellationToken cancellationToken = default)
     {
         var content = new DaprComponentSchema(component.Name, type);
-        await ConfigureDaprComponent(component, content);
+        await ConfigureDaprComponent(component, content, cancellationToken);
+        await content.ResolveAllValuesAsync(cancellationToken);
         return content.ToString();
     }
 
-    private static async Task ConfigureDaprComponent(DaprComponentResource component, DaprComponentSchema content)
+    private static async Task ConfigureDaprComponent(DaprComponentResource component, DaprComponentSchema content, CancellationToken cancellationToken = default)
     {
         if (component.TryGetAnnotationsOfType<DaprComponentSecretAnnotation>(out var secrets) && secrets.Any())
         {
@@ -567,7 +637,7 @@ private static async Task ConfigureDaprComponent(DaprComponentResource component
         {
             foreach (var annotation in annotations)
             {
-                await annotation.Configure(content);
+                await annotation.Configure(content, cancellationToken);
             }
         }
     }
diff --git a/src/Shared/Dapr/Core/DaprMetadataResourceBuilderExtensions.cs b/src/Shared/Dapr/Core/DaprMetadataResourceBuilderExtensions.cs
index 7944bb871..6c4aa04fb 100644
--- a/src/Shared/Dapr/Core/DaprMetadataResourceBuilderExtensions.cs
+++ b/src/Shared/Dapr/Core/DaprMetadataResourceBuilderExtensions.cs
@@ -16,7 +16,7 @@ public static class DaprMetadataResourceBuilderExtensions
     /// <param name="value"></param>
     /// <returns></returns>
     public static IResourceBuilder<IDaprComponentResource> WithMetadata(this IResourceBuilder<IDaprComponentResource> builder, string name, string value) =>
-        builder.WithAnnotation(new DaprComponentConfigurationAnnotation(schema =>
+        builder.WithAnnotation(new DaprComponentConfigurationAnnotation((schema, cancellationToken) =>
         {
             var existing = schema.Spec.Metadata.Find(m => m.Name == name);
             if (existing is not null)
@@ -32,6 +32,62 @@ public static IResourceBuilder<IDaprComponentResource> WithMetadata(this IResour
         }));
 
 
+    /// <summary>
+    /// Adds a value provider as metadata to the Dapr component that will be resolved at runtime.
+    /// </summary>
+    /// <param name="builder">The resource builder for the Dapr component being configured.</param>
+    /// <param name="name">The name of the metadata property to add to the Dapr component configuration.</param>
+    /// <param name="valueProvider">The value provider (e.g., EndpointReference, ConnectionStringReference) whose value will be resolved at runtime.
+    /// The provider's value is stored as an environment variable and referenced through Dapr's secret key reference mechanism.</param>
+    /// <returns>The resource builder instance.</returns>
+    /// <remarks>
+    /// This method enables dynamic configuration of Dapr components by:
+    /// <list type="bullet">
+    /// <item>Creating a unique environment variable name based on the component and metadata names</item>
+    /// <item>Storing the value provider reference for runtime resolution</item>
+    /// <item>Configuring the metadata to use a secretKeyRef pointing to the environment variable</item>
+    /// </list>
+    /// The environment variable name format is: {COMPONENT_NAME}_{METADATA_NAME} (uppercased, hyphens replaced with underscores).
+    /// This approach allows for secure injection of dynamic values like endpoint URLs or connection strings that are only known at runtime.
+    /// </remarks>
+    /// <example>
+    /// <code>
+    /// var cache = builder.AddDaprComponent("cache", "state.redis")
+    ///     .WithMetadata("redisHost", redis.GetEndpoint("tcp"));
+    /// </code>
+    /// </example>
+    public static IResourceBuilder<IDaprComponentResource> WithMetadata(this IResourceBuilder<IDaprComponentResource> builder, string name, IValueProvider valueProvider)
+    {
+        // Create a unique environment variable name for this value provider
+        // Note: We avoid using DAPR_ prefix as it's restricted by Dapr's local.env secret store
+        var envVarName = $"{builder.Resource.Name}_{name}".ToUpperInvariant().Replace("-", "_");
+        
+        // Add an annotation to track this value provider reference
+        builder.WithAnnotation(new DaprComponentValueProviderAnnotation(name, envVarName, valueProvider));
+        
+        return builder.WithAnnotation(new DaprComponentConfigurationAnnotation((schema, cancellationToken) =>
+        {
+            var existing = schema.Spec.Metadata.Find(m => m.Name == name);
+            if (existing is not null)
+            {
+                schema.Spec.Metadata.Remove(existing);
+            }
+
+            // Use a secretKeyRef to reference the environment variable
+            // This will be resolved from the environment at runtime
+            schema.Spec.Metadata.Add(new DaprComponentSpecMetadataSecret
+            {
+                Name = name,
+                SecretKeyRef = new DaprSecretKeyRef
+                {
+                    Name = envVarName,
+                    Key = envVarName
+                }
+            });
+            return Task.CompletedTask;
+        }));
+    }
+
     /// <summary>
     /// Adds a parameter resource as metadata to the Dapr component
     /// </summary>
@@ -44,7 +100,7 @@ public static IResourceBuilder<IDaprComponentResource> WithMetadata(this IResour
         if (parameterResource.Secret)
         {
             return builder.WithAnnotation(new DaprComponentSecretAnnotation(parameterResource.Name, parameterResource))
-                          .WithAnnotation(new DaprComponentConfigurationAnnotation(schema =>
+                          .WithAnnotation(new DaprComponentConfigurationAnnotation((schema, cancellationToken) =>
                           {
                               var existing = schema.Spec.Metadata.Find(m => m.Name == name);
                               if (existing is not null)
@@ -64,7 +120,7 @@ public static IResourceBuilder<IDaprComponentResource> WithMetadata(this IResour
                           }));
         }
 
-        return builder.WithAnnotation(new DaprComponentConfigurationAnnotation(async schema =>
+        return builder.WithAnnotation(new DaprComponentConfigurationAnnotation(async (schema, cancellationToken) =>
         {
             var existing = schema.Spec.Metadata.Find(m => m.Name == name);
             if (existing is not null)
@@ -74,7 +130,7 @@ public static IResourceBuilder<IDaprComponentResource> WithMetadata(this IResour
             schema.Spec.Metadata.Add(new DaprComponentSpecMetadataValue
             {
                 Name = name,
-                Value = (await parameterResource.GetValueAsync(default))!
+                Value = (await parameterResource.GetValueAsync(cancellationToken))!
             });
         }));
     }
diff --git a/src/Shared/Dapr/Core/DaprSidecarEvents.cs b/src/Shared/Dapr/Core/DaprSidecarEvents.cs
new file mode 100644
index 000000000..6f32f906b
--- /dev/null
+++ b/src/Shared/Dapr/Core/DaprSidecarEvents.cs
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Aspire.Hosting.ApplicationModel;
+using Aspire.Hosting.Eventing;
+
+namespace CommunityToolkit.Aspire.Hosting.Dapr;
+
+/// <summary>
+/// Event published when a Dapr sidecar becomes available.
+/// </summary>
+public class DaprSidecarAvailableEvent(IDaprSidecarResource resource, IServiceProvider services)
+    : IDistributedApplicationResourceEvent
+{
+    /// <summary>
+    /// Gets the Dapr sidecar resource that became available.
+    /// </summary>
+    public IResource Resource { get; } = resource;
+
+    /// <summary>
+    /// Gets the service provider.
+    /// </summary>
+    public IServiceProvider Services { get; } = services;
+}
\ No newline at end of file
diff --git a/src/Shared/Dapr/Core/IDaprSidecarResource.cs b/src/Shared/Dapr/Core/IDaprSidecarResource.cs
index 8c0842360..b611323f9 100644
--- a/src/Shared/Dapr/Core/IDaprSidecarResource.cs
+++ b/src/Shared/Dapr/Core/IDaprSidecarResource.cs
@@ -8,6 +8,6 @@ namespace CommunityToolkit.Aspire.Hosting.Dapr;
 /// <summary>
 /// Represents a Dapr sidecar resource.
 /// </summary>
-public interface IDaprSidecarResource : IResource
+public interface IDaprSidecarResource : IResource, IResourceWithWaitSupport
 {
 }
diff --git a/src/Shared/Dapr/Core/IDistributedApplicationBuilderExtensions.shared.cs b/src/Shared/Dapr/Core/IDistributedApplicationBuilderExtensions.shared.cs
index 1c0922add..096243338 100644
--- a/src/Shared/Dapr/Core/IDistributedApplicationBuilderExtensions.shared.cs
+++ b/src/Shared/Dapr/Core/IDistributedApplicationBuilderExtensions.shared.cs
@@ -7,6 +7,7 @@
 using Aspire.Hosting.Publishing;
 using Aspire.Hosting.Utils;
 using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
 
 namespace Aspire.Hosting;
 
@@ -27,15 +28,58 @@ public static partial class IDistributedApplicationBuilderExtensions
     public static IResourceBuilder<IDaprComponentResource> AddDaprComponent(this IDistributedApplicationBuilder builder, [ResourceName] string name, string type, DaprComponentOptions? options = null)
     {
         var resource = new DaprComponentResource(name, type) { Options = options };
-        return builder
+        var resourceBuilder = builder
             .AddResource(resource)
             .WithInitialState(new()
             {
                 Properties = [],
                 ResourceType = "DaprComponent",
                 IsHidden = true,
+                State = KnownResourceStates.NotStarted
             })
             .WithAnnotation(new ManifestPublishingCallbackAnnotation(context => WriteDaprComponentResourceToManifest(context, resource)));
+        
+        // Set up component lifecycle to manage state transitions
+        SetupComponentLifecycle(resourceBuilder);
+        
+        return resourceBuilder;
+    }
+    
+    private static void SetupComponentLifecycle(IResourceBuilder<IDaprComponentResource> componentBuilder)
+    {
+        // Hook into the component initialization for state management
+        componentBuilder.OnInitializeResource(async (component, evt, ct) =>
+        {
+            try
+            {
+                // Update state to starting
+                await evt.Notifications.PublishUpdateAsync(component, s => s with
+                {
+                    State = KnownResourceStates.Starting
+                }).ConfigureAwait(false);
+
+                // Publish before started event
+                await evt.Eventing.PublishAsync(new BeforeResourceStartedEvent(component, evt.Services), ct).ConfigureAwait(false);
+
+                // Update state to running
+                await evt.Notifications.PublishUpdateAsync(component, s => s with
+                {
+                    State = KnownResourceStates.Running
+                }).ConfigureAwait(false);
+                
+                evt.Logger.LogInformation("Dapr component '{ComponentName}' started successfully", component.Name);
+            }
+            catch (Exception ex)
+            {
+                evt.Logger.LogError(ex, "Failed to initialize Dapr component '{ComponentName}'", component.Name);
+
+                // Update state to failed
+                await evt.Notifications.PublishUpdateAsync(component, s => s with
+                {
+                    State = KnownResourceStates.FailedToStart
+                }).ConfigureAwait(false);
+            }
+        });
     }
 
     /// <summary>
diff --git a/src/Shared/Dapr/Core/IDistributedApplicationComponentBuilderExtensions.cs b/src/Shared/Dapr/Core/IDistributedApplicationComponentBuilderExtensions.cs
index 19848eb19..9bab7db51 100644
--- a/src/Shared/Dapr/Core/IDistributedApplicationComponentBuilderExtensions.cs
+++ b/src/Shared/Dapr/Core/IDistributedApplicationComponentBuilderExtensions.cs
@@ -3,6 +3,7 @@
 
 using Aspire.Hosting.ApplicationModel;
 using CommunityToolkit.Aspire.Hosting.Dapr;
+using Microsoft.Extensions.Logging;
 
 namespace Aspire.Hosting;
 
@@ -60,13 +61,106 @@ public static IResourceBuilder<T> WithDaprSidecar<T>(this IResourceBuilder<T> bu
                                                            Properties = [],
                                                            ResourceType = "DaprSidecar",
                                                            IsHidden = true,
+                                                           State = KnownResourceStates.NotStarted
                                                        });
 
         configureSidecar(sidecarBuilder);
 
+        SetupSidecarLifecycle(builder, sidecarBuilder);
+
         return builder.WithAnnotation(new DaprSidecarAnnotation(sidecarBuilder.Resource));
     }
 
+    private static void SetupSidecarLifecycle<T>(IResourceBuilder<T> parentBuilder, IResourceBuilder<IDaprSidecarResource> sidecarBuilder) where T : IResource
+    {
+        var dependencies = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+        var valueProviderResources = new List<IResourceBuilder<IResource>>();
+        
+        // Find component references from the parent resource
+        if (parentBuilder.Resource.TryGetAnnotationsOfType<DaprComponentReferenceAnnotation>(out var componentRefs))
+        {
+            foreach (var componentRef in componentRefs)
+            {
+                // Check for value provider annotations on the component
+                if (componentRef.Component.TryGetAnnotationsOfType<DaprComponentValueProviderAnnotation>(out var valueProviderAnnotations))
+                {
+                    foreach (var annotation in valueProviderAnnotations)
+                    {
+                        // Extract resource references from value providers
+                        if (annotation.ValueProvider is IResourceWithoutLifetime)
+                        {
+                            // Skip waiting for resources without a lifetime
+                            continue;
+                        }
+
+                        if (annotation.ValueProvider is IResource resource)
+                        {
+                            if (dependencies.Add(resource.Name))
+                            {
+                                // Create resource builder for waiting
+                                var resourceBuilder = parentBuilder.ApplicationBuilder.CreateResourceBuilder(resource);
+                                valueProviderResources.Add(resourceBuilder);
+                                // Add wait dependency using WaitFor (waits for resource to be available/running)
+                                sidecarBuilder.WaitFor(resourceBuilder);
+                            }
+                        }
+                        else if (annotation.ValueProvider is IValueWithReferences valueWithReferences)
+                        {
+                            foreach (var innerRef in valueWithReferences.References.OfType<IResource>())
+                            {
+                                if (dependencies.Add(innerRef.Name))
+                                {
+                                    // Create resource builder for waiting
+                                    var resourceBuilder = parentBuilder.ApplicationBuilder.CreateResourceBuilder(innerRef);
+                                    valueProviderResources.Add(resourceBuilder);
+                                    // Add wait dependency using WaitFor (waits for resource to be available/running)
+                                    sidecarBuilder.WaitFor(resourceBuilder);
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Hook into the sidecar initialization for state management and event publishing
+        sidecarBuilder.OnInitializeResource(async (sidecar, evt, ct) =>
+        {
+            try
+            {
+                // Update state to starting
+                await evt.Notifications.PublishUpdateAsync(sidecar, s => s with
+                {
+                    State = KnownResourceStates.Starting
+                }).ConfigureAwait(false);
+
+                // Publish before started event
+                await evt.Eventing.PublishAsync(new BeforeResourceStartedEvent(sidecar, evt.Services), ct).ConfigureAwait(false);
+
+                // Update state to running
+                await evt.Notifications.PublishUpdateAsync(sidecar, s => s with
+                {
+                    State = KnownResourceStates.Running
+                }).ConfigureAwait(false);
+
+                // Publish sidecar available event
+                await evt.Eventing.PublishAsync(new DaprSidecarAvailableEvent(sidecar, evt.Services), ct).ConfigureAwait(false);
+                
+                evt.Logger.LogInformation("Dapr sidecar '{SidecarName}' started successfully", sidecar.Name);
+            }
+            catch (Exception ex)
+            {
+                evt.Logger.LogError(ex, "Failed to initialize Dapr sidecar '{SidecarName}'", sidecar.Name);
+
+                // Update state to failed
+                await evt.Notifications.PublishUpdateAsync(sidecar, s => s with
+                {
+                    State = KnownResourceStates.FailedToStart
+                }).ConfigureAwait(false);
+            }
+        });
+    }
+
     /// <summary>
     /// Configures a Dapr sidecar with the specified options.
     /// </summary>
diff --git a/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs b/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs
index ce9ce838b..0156c49d8 100644
--- a/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs
+++ b/tests/CommunityToolkit.Aspire.Hosting.Dapr.Tests/WithDaprSidecarTests.cs
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 
 using Aspire.Hosting;
+using Aspire.Hosting.ApplicationModel;
 
 namespace CommunityToolkit.Aspire.Hosting.Dapr.Tests;
 
@@ -60,4 +61,29 @@ public void OptionsCanBeConfiguredUsingCallback()
 
         Assert.Equal("appId", annotation.Options.AppId);
     }
+
+    [Fact]
+    public void DaprSidecarSupportsWaitFor()
+    {
+        var builder = DistributedApplication.CreateBuilder();
+
+        builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceA>("service-a")
+            .WithDaprSidecar();
+
+        var sidecarResource = Assert.Single(builder.Resources.OfType<IDaprSidecarResource>());
+
+        // Verify that IDaprSidecarResource implements IResourceWithWaitSupport
+        Assert.IsAssignableFrom<IResourceWithWaitSupport>(sidecarResource);
+
+        // Create a resource builder and use it with WaitFor
+        var sidecarResourceBuilder = builder.CreateResourceBuilder(sidecarResource);
+
+        var serviceB = builder.AddProject<Projects.CommunityToolkit_Aspire_Hosting_Dapr_ServiceB>("service-b")
+            .WaitFor(sidecarResourceBuilder);
+
+        // Verify the wait annotation was added
+        Assert.NotNull(serviceB);
+        var waitAnnotation = Assert.Single(serviceB.Resource.Annotations.OfType<WaitAnnotation>());
+        Assert.Equal(sidecarResource.Name, waitAnnotation.Resource.Name);
+    }
 }
diff --git a/tests/dapr-shared/ResourceBuilderExtensionsTests.cs b/tests/dapr-shared/ResourceBuilderExtensionsTests.cs
index 72db8b2ce..3d8263cf0 100644
--- a/tests/dapr-shared/ResourceBuilderExtensionsTests.cs
+++ b/tests/dapr-shared/ResourceBuilderExtensionsTests.cs
@@ -1,6 +1,8 @@
 ﻿using Aspire.Hosting;
+using Aspire.Hosting.ApplicationModel;
 using Aspire.Hosting.Utils;
 using System.Runtime.CompilerServices;
+using Xunit;
 
 namespace CommunityToolkit.Aspire.Hosting.Dapr.Tests;
 public class ResourceBuilderExtensionsTests
@@ -34,4 +36,100 @@ public void WithMetadataUsingSecretParameterResourceAddsDaprComponentSecretAnnot
         Assert.Single(resource.Annotations.OfType<DaprComponentSecretAnnotation>());
     }
 
+    [Fact]
+    public void WithMetadataUsingEndpointReferenceAddsValueProviderAnnotation()
+    {
+        // Arrange
+        var builder = DistributedApplication.CreateBuilder();
+        var redis = builder.AddRedis("redis");
+        var pubsub = builder.AddDaprPubSub("pubsub");
+        
+        // Act
+        pubsub.WithMetadata("redisHost", redis.GetEndpoint("tcp"));
+        
+        // Assert
+        var resource = Assert.Single(builder.Resources.OfType<DaprComponentResource>());
+        
+        // Check for value provider annotation
+        Assert.True(resource.TryGetAnnotationsOfType<DaprComponentValueProviderAnnotation>(out var endpointAnnotations));
+        var endpointAnnotation = Assert.Single(endpointAnnotations);
+        Assert.Equal("redisHost", endpointAnnotation.MetadataName);
+        Assert.Contains("PUBSUB_", endpointAnnotation.EnvironmentVariableName);
+        
+        // Check for configuration annotation that sets up secretKeyRef
+        Assert.True(resource.TryGetAnnotationsOfType<DaprComponentConfigurationAnnotation>(out var configAnnotations));
+        Assert.Single(configAnnotations);
+    }
+
+    [Fact]
+    public async Task WithMetadataUsingValueProviderGeneratesSecretKeyRefInYaml()
+    {
+        // Arrange
+        var builder = DistributedApplication.CreateBuilder();
+        var redis = builder.AddRedis("redis");
+        var pubsub = builder.AddDaprPubSub("pubsub")
+            .WithMetadata("redisHost", redis.GetEndpoint("tcp"));
+        
+        // Act
+        var resource = Assert.Single(builder.Resources.OfType<DaprComponentResource>());
+        var schema = new DaprComponentSchema("pubsub", "pubsub.redis");
+        
+        // Apply configurations
+        if (resource.TryGetAnnotationsOfType<DaprComponentConfigurationAnnotation>(out var annotations))
+        {
+            foreach (var annotation in annotations)
+            {
+                await annotation.Configure(schema, default);
+            }
+        }
+        
+        // Assert
+        Assert.Single(schema.Spec.Metadata);
+        var metadataItem = Assert.IsType<DaprComponentSpecMetadataSecret>(schema.Spec.Metadata[0]);
+        Assert.Equal("redisHost", metadataItem.Name);
+        Assert.NotNull(metadataItem.SecretKeyRef);
+        Assert.Contains("PUBSUB_", metadataItem.SecretKeyRef.Key);
+        
+        // Check that YAML contains secretKeyRef
+        var yaml = schema.ToString();
+        Assert.Contains("secretKeyRef:", yaml);
+        Assert.Contains("name: PUBSUB_", yaml);
+    }
+
+    [Fact]
+    public void WithMetadataAcceptsAnyValueProvider()
+    {
+        // Arrange
+        var builder = DistributedApplication.CreateBuilder();
+        var customValueProvider = new TestValueProvider("custom-value");
+        var pubsub = builder.AddDaprPubSub("pubsub");
+
+        // Act - This should compile and work because WithMetadata now accepts IValueProvider
+        pubsub.WithMetadata("customValue", customValueProvider);
+
+        // Assert
+        var resource = Assert.Single(builder.Resources.OfType<DaprComponentResource>());
+
+        // Check for value provider annotation
+        Assert.True(resource.TryGetAnnotationsOfType<DaprComponentValueProviderAnnotation>(out var annotations));
+        var annotation = Assert.Single(annotations);
+        Assert.Equal("customValue", annotation.MetadataName);
+        Assert.Same(customValueProvider, annotation.ValueProvider);
+    }
+
+    // Test helper class that implements IValueProvider
+    private class TestValueProvider : global::Aspire.Hosting.ApplicationModel.IValueProvider
+    {
+        private readonly string _value;
+
+        public TestValueProvider(string value)
+        {
+            _value = value;
+        }
+
+        public ValueTask<string?> GetValueAsync(CancellationToken cancellationToken = default)
+        {
+            return ValueTask.FromResult<string?>(_value);
+        }
+    }
 }
