diff --git a/BUILD b/BUILD
index e4ee8e93f71681b9b8d73be98eb309ca2768e014..d2d365ac64f3ab592d97c270fc0c8190e0054892 100644
--- a/BUILD
+++ b/BUILD
@@ -311,7 +311,6 @@ cc_library(
     "src/core/ext/client_channel/resolver.h",
     "src/core/ext/client_channel/resolver_factory.h",
     "src/core/ext/client_channel/resolver_registry.h",
-    "src/core/ext/client_channel/resolver_result.h",
     "src/core/ext/client_channel/subchannel.h",
     "src/core/ext/client_channel/subchannel_index.h",
     "src/core/ext/client_channel/uri_parser.h",
@@ -504,7 +503,6 @@ cc_library(
     "src/core/ext/client_channel/resolver.c",
     "src/core/ext/client_channel/resolver_factory.c",
     "src/core/ext/client_channel/resolver_registry.c",
-    "src/core/ext/client_channel/resolver_result.c",
     "src/core/ext/client_channel/subchannel.c",
     "src/core/ext/client_channel/subchannel_index.c",
     "src/core/ext/client_channel/uri_parser.c",
@@ -711,7 +709,6 @@ cc_library(
     "src/core/ext/client_channel/resolver.h",
     "src/core/ext/client_channel/resolver_factory.h",
     "src/core/ext/client_channel/resolver_registry.h",
-    "src/core/ext/client_channel/resolver_result.h",
     "src/core/ext/client_channel/subchannel.h",
     "src/core/ext/client_channel/subchannel_index.h",
     "src/core/ext/client_channel/uri_parser.h",
@@ -887,7 +884,6 @@ cc_library(
     "src/core/ext/client_channel/resolver.c",
     "src/core/ext/client_channel/resolver_factory.c",
     "src/core/ext/client_channel/resolver_registry.c",
-    "src/core/ext/client_channel/resolver_result.c",
     "src/core/ext/client_channel/subchannel.c",
     "src/core/ext/client_channel/subchannel_index.c",
     "src/core/ext/client_channel/uri_parser.c",
@@ -1088,7 +1084,6 @@ cc_library(
     "src/core/ext/client_channel/resolver.h",
     "src/core/ext/client_channel/resolver_factory.h",
     "src/core/ext/client_channel/resolver_registry.h",
-    "src/core/ext/client_channel/resolver_result.h",
     "src/core/ext/client_channel/subchannel.h",
     "src/core/ext/client_channel/subchannel_index.h",
     "src/core/ext/client_channel/uri_parser.h",
@@ -1257,7 +1252,6 @@ cc_library(
     "src/core/ext/client_channel/resolver.c",
     "src/core/ext/client_channel/resolver_factory.c",
     "src/core/ext/client_channel/resolver_registry.c",
-    "src/core/ext/client_channel/resolver_result.c",
     "src/core/ext/client_channel/subchannel.c",
     "src/core/ext/client_channel/subchannel_index.c",
     "src/core/ext/client_channel/uri_parser.c",
@@ -2207,7 +2201,6 @@ objc_library(
     "src/core/ext/client_channel/resolver.c",
     "src/core/ext/client_channel/resolver_factory.c",
     "src/core/ext/client_channel/resolver_registry.c",
-    "src/core/ext/client_channel/resolver_result.c",
     "src/core/ext/client_channel/subchannel.c",
     "src/core/ext/client_channel/subchannel_index.c",
     "src/core/ext/client_channel/uri_parser.c",
@@ -2416,7 +2409,6 @@ objc_library(
     "src/core/ext/client_channel/resolver.h",
     "src/core/ext/client_channel/resolver_factory.h",
     "src/core/ext/client_channel/resolver_registry.h",
-    "src/core/ext/client_channel/resolver_result.h",
     "src/core/ext/client_channel/subchannel.h",
     "src/core/ext/client_channel/subchannel_index.h",
     "src/core/ext/client_channel/uri_parser.h",
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2f301f54b9d1b9720e7d9a164bef9b20ad1e8468..1877aa28773044e4c1995dd3d186d9932fe7068b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -462,7 +462,6 @@ add_library(grpc
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
-  src/core/ext/client_channel/resolver_result.c
   src/core/ext/client_channel/subchannel.c
   src/core/ext/client_channel/subchannel_index.c
   src/core/ext/client_channel/uri_parser.c
@@ -709,7 +708,6 @@ add_library(grpc_cronet
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
-  src/core/ext/client_channel/resolver_result.c
   src/core/ext/client_channel/subchannel.c
   src/core/ext/client_channel/subchannel_index.c
   src/core/ext/client_channel/uri_parser.c
@@ -953,7 +951,6 @@ add_library(grpc_unsecure
   src/core/ext/client_channel/resolver.c
   src/core/ext/client_channel/resolver_factory.c
   src/core/ext/client_channel/resolver_registry.c
-  src/core/ext/client_channel/resolver_result.c
   src/core/ext/client_channel/subchannel.c
   src/core/ext/client_channel/subchannel_index.c
   src/core/ext/client_channel/uri_parser.c
diff --git a/Makefile b/Makefile
index f0dec1a4a36f6e15130583576d297f46f3d0e98c..e789b1f38b6030cf4c3a576c597720939a943e0a 100644
--- a/Makefile
+++ b/Makefile
@@ -2747,7 +2747,6 @@ LIBGRPC_SRC = \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
-    src/core/ext/client_channel/resolver_result.c \
     src/core/ext/client_channel/subchannel.c \
     src/core/ext/client_channel/subchannel_index.c \
     src/core/ext/client_channel/uri_parser.c \
@@ -3012,7 +3011,6 @@ LIBGRPC_CRONET_SRC = \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
-    src/core/ext/client_channel/resolver_result.c \
     src/core/ext/client_channel/subchannel.c \
     src/core/ext/client_channel/subchannel_index.c \
     src/core/ext/client_channel/uri_parser.c \
@@ -3501,7 +3499,6 @@ LIBGRPC_UNSECURE_SRC = \
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
-    src/core/ext/client_channel/resolver_result.c \
     src/core/ext/client_channel/subchannel.c \
     src/core/ext/client_channel/subchannel_index.c \
     src/core/ext/client_channel/uri_parser.c \
diff --git a/binding.gyp b/binding.gyp
index 390cc52c8f38a32922002c3776508a19fe98c476..15d57888f65926200964d44ee97116a65f2351d3 100644
--- a/binding.gyp
+++ b/binding.gyp
@@ -740,7 +740,6 @@
         'src/core/ext/client_channel/resolver.c',
         'src/core/ext/client_channel/resolver_factory.c',
         'src/core/ext/client_channel/resolver_registry.c',
-        'src/core/ext/client_channel/resolver_result.c',
         'src/core/ext/client_channel/subchannel.c',
         'src/core/ext/client_channel/subchannel_index.c',
         'src/core/ext/client_channel/uri_parser.c',
diff --git a/build.yaml b/build.yaml
index 17828ae8eb61fc660fd40811e6625dc388b1d9a7..0400fa7b2130040fdfda64a4a024a25d8fa3a8fb 100644
--- a/build.yaml
+++ b/build.yaml
@@ -382,7 +382,6 @@ filegroups:
   - src/core/ext/client_channel/resolver.h
   - src/core/ext/client_channel/resolver_factory.h
   - src/core/ext/client_channel/resolver_registry.h
-  - src/core/ext/client_channel/resolver_result.h
   - src/core/ext/client_channel/subchannel.h
   - src/core/ext/client_channel/subchannel_index.h
   - src/core/ext/client_channel/uri_parser.h
@@ -403,7 +402,6 @@ filegroups:
   - src/core/ext/client_channel/resolver.c
   - src/core/ext/client_channel/resolver_factory.c
   - src/core/ext/client_channel/resolver_registry.c
-  - src/core/ext/client_channel/resolver_result.c
   - src/core/ext/client_channel/subchannel.c
   - src/core/ext/client_channel/subchannel_index.c
   - src/core/ext/client_channel/uri_parser.c
diff --git a/config.m4 b/config.m4
index 298708a83972058062ec82cf40f4b9a57f0e42d5..14fda1d4e014147b0750215a855755ad64cc9a4e 100644
--- a/config.m4
+++ b/config.m4
@@ -256,7 +256,6 @@ if test "$PHP_GRPC" != "no"; then
     src/core/ext/client_channel/resolver.c \
     src/core/ext/client_channel/resolver_factory.c \
     src/core/ext/client_channel/resolver_registry.c \
-    src/core/ext/client_channel/resolver_result.c \
     src/core/ext/client_channel/subchannel.c \
     src/core/ext/client_channel/subchannel_index.c \
     src/core/ext/client_channel/uri_parser.c \
diff --git a/gRPC-Core.podspec b/gRPC-Core.podspec
index 6fc65f6c6934a34dbcd9baf0b29ad0cc696a431c..4e1ae314c1066801029791f76da46966a8ba0ef4 100644
--- a/gRPC-Core.podspec
+++ b/gRPC-Core.podspec
@@ -398,7 +398,6 @@ Pod::Spec.new do |s|
                       'src/core/ext/client_channel/resolver.h',
                       'src/core/ext/client_channel/resolver_factory.h',
                       'src/core/ext/client_channel/resolver_registry.h',
-                      'src/core/ext/client_channel/resolver_result.h',
                       'src/core/ext/client_channel/subchannel.h',
                       'src/core/ext/client_channel/subchannel_index.h',
                       'src/core/ext/client_channel/uri_parser.h',
@@ -595,7 +594,6 @@ Pod::Spec.new do |s|
                       'src/core/ext/client_channel/resolver.c',
                       'src/core/ext/client_channel/resolver_factory.c',
                       'src/core/ext/client_channel/resolver_registry.c',
-                      'src/core/ext/client_channel/resolver_result.c',
                       'src/core/ext/client_channel/subchannel.c',
                       'src/core/ext/client_channel/subchannel_index.c',
                       'src/core/ext/client_channel/uri_parser.c',
@@ -793,7 +791,6 @@ Pod::Spec.new do |s|
                               'src/core/ext/client_channel/resolver.h',
                               'src/core/ext/client_channel/resolver_factory.h',
                               'src/core/ext/client_channel/resolver_registry.h',
-                              'src/core/ext/client_channel/resolver_result.h',
                               'src/core/ext/client_channel/subchannel.h',
                               'src/core/ext/client_channel/subchannel_index.h',
                               'src/core/ext/client_channel/uri_parser.h',
diff --git a/grpc.gemspec b/grpc.gemspec
index d991d561f4dbf1b3a46370486e6fbd239209b015..42b98dccd4bdc621c177b4abe06d06792d156d84 100755
--- a/grpc.gemspec
+++ b/grpc.gemspec
@@ -318,7 +318,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/client_channel/resolver.h )
   s.files += %w( src/core/ext/client_channel/resolver_factory.h )
   s.files += %w( src/core/ext/client_channel/resolver_registry.h )
-  s.files += %w( src/core/ext/client_channel/resolver_result.h )
   s.files += %w( src/core/ext/client_channel/subchannel.h )
   s.files += %w( src/core/ext/client_channel/subchannel_index.h )
   s.files += %w( src/core/ext/client_channel/uri_parser.h )
@@ -515,7 +514,6 @@ Gem::Specification.new do |s|
   s.files += %w( src/core/ext/client_channel/resolver.c )
   s.files += %w( src/core/ext/client_channel/resolver_factory.c )
   s.files += %w( src/core/ext/client_channel/resolver_registry.c )
-  s.files += %w( src/core/ext/client_channel/resolver_result.c )
   s.files += %w( src/core/ext/client_channel/subchannel.c )
   s.files += %w( src/core/ext/client_channel/subchannel_index.c )
   s.files += %w( src/core/ext/client_channel/uri_parser.c )
diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h
index a3fc683e579b4eb8095f2288233ff6cb083dee00..0be7ab2ad2353a2c239e0a263ab6ef5b12081910 100644
--- a/include/grpc/impl/codegen/grpc_types.h
+++ b/include/grpc/impl/codegen/grpc_types.h
@@ -204,6 +204,13 @@ typedef struct {
 /** Service config data, to be passed to subchannels.
     Not intended for external use. */
 #define GRPC_ARG_SERVICE_CONFIG "grpc.service_config"
+/** LB policy name. */
+#define GRPC_ARG_LB_POLICY_NAME "grpc.lb_policy_name"
+/** Server name. Not intended for external use. */
+#define GRPC_ARG_SERVER_NAME "grpc.server_name"
+/** Resolved addresses in a form used by the LB policy.
+    Not intended for external use. */
+#define GRPC_ARG_LB_ADDRESSES "grpc.lb_addresses"
 /** \} */
 
 /** Result of a grpc call. If the caller satisfies the prerequisites of a
diff --git a/package.xml b/package.xml
index 5f637f816e0158621415ce60ac040b4f8d12b81e..36a3a193d01d793c72ba9d6c577b4287592915a6 100644
--- a/package.xml
+++ b/package.xml
@@ -325,7 +325,6 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.h" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_result.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.h" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.h" role="src" />
@@ -522,7 +521,6 @@
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_factory.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_registry.c" role="src" />
-    <file baseinstalldir="/" name="src/core/ext/client_channel/resolver_result.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/subchannel_index.c" role="src" />
     <file baseinstalldir="/" name="src/core/ext/client_channel/uri_parser.c" role="src" />
diff --git a/src/core/ext/client_channel/README.md b/src/core/ext/client_channel/README.md
index eda01e3e715f127e4e1e3d05f573f2ac2c49e58e..7c209db12e32fa3def023b9c3c1bfb8d5f60ae14 100644
--- a/src/core/ext/client_channel/README.md
+++ b/src/core/ext/client_channel/README.md
@@ -5,28 +5,27 @@ This library provides high level configuration machinery to construct client
 channels and load balance between them.
 
 Each grpc_channel is created with a grpc_resolver. It is the resolver's duty
-to resolve a name into configuration data for the channel. Such configuration
-data might include:
+to resolve a name into a set of arguments for the channel. Such arguments
+might include:
 
 - a list of (ip, port) addresses to connect to
 - a load balancing policy to decide which server to send a request to
 - a set of filters to mutate outgoing requests (say, by adding metadata)
 
-The resolver provides this data as a stream of grpc_resolver_result objects to
-the channel. We represent configuration as a stream so that it can be changed
-by the resolver during execution, by reacting to external events (such as a
-new configuration file being pushed to some store).
+The resolver provides this data as a stream of grpc_channel_args objects to
+the channel. We represent arguments as a stream so that they can be changed
+by the resolver during execution, by reacting to external events (such as
+new service configuration data being pushed to some store).
 
 
 Load Balancing
 --------------
 
-Load balancing configuration is provided by a grpc_lb_policy object, stored as
-part of grpc_resolver_result.
+Load balancing configuration is provided by a grpc_lb_policy object.
 
-The primary job of the load balancing policies is to pick a target server given only the
-initial metadata for a request. It does this by providing a grpc_subchannel
-object to the owning channel.
+The primary job of the load balancing policies is to pick a target server
+given only the initial metadata for a request. It does this by providing
+a grpc_subchannel object to the owning channel.
 
 
 Sub-Channels
diff --git a/src/core/ext/client_channel/client_channel.c b/src/core/ext/client_channel/client_channel.c
index 55bb877576f7e4f5eb9d4663edbc15b241bb8e43..9399b4f1a564cf641fc1e2f19abb6a2d0cd94720 100644
--- a/src/core/ext/client_channel/client_channel.c
+++ b/src/core/ext/client_channel/client_channel.c
@@ -127,7 +127,7 @@ typedef struct client_channel_channel_data {
   /** maps method names to method_parameters structs */
   grpc_mdstr_hash_table *method_params_table;
   /** incoming resolver result - set by resolver.next() */
-  grpc_resolver_result *resolver_result;
+  grpc_channel_args *resolver_result;
   /** a list of closures that are all waiting for config to come in */
   grpc_closure_list waiting_for_config_closures;
   /** resolver callback */
@@ -232,35 +232,42 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
 
   if (chand->resolver_result != NULL) {
     grpc_lb_policy_args lb_policy_args;
-    lb_policy_args.server_name =
-        grpc_resolver_result_get_server_name(chand->resolver_result);
-    lb_policy_args.addresses =
-        grpc_resolver_result_get_addresses(chand->resolver_result);
-    lb_policy_args.additional_args =
-        grpc_resolver_result_get_lb_policy_args(chand->resolver_result);
+    lb_policy_args.args = chand->resolver_result;
     lb_policy_args.client_channel_factory = chand->client_channel_factory;
 
+    // Find LB policy name.
+    const char *lb_policy_name = NULL;
+    const grpc_arg *channel_arg =
+        grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_POLICY_NAME);
+    if (channel_arg != NULL) {
+      GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
+      lb_policy_name = channel_arg->value.string;
+    }
     // Special case: If all of the addresses are balancer addresses,
     // assume that we should use the grpclb policy, regardless of what the
     // resolver actually specified.
-    const char *lb_policy_name =
-        grpc_resolver_result_get_lb_policy_name(chand->resolver_result);
-    bool found_backend_address = false;
-    for (size_t i = 0; i < lb_policy_args.addresses->num_addresses; ++i) {
-      if (!lb_policy_args.addresses->addresses[i].is_balancer) {
-        found_backend_address = true;
-        break;
+    channel_arg =
+        grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_LB_ADDRESSES);
+    if (channel_arg != NULL) {
+      GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
+      grpc_lb_addresses *addresses = channel_arg->value.pointer.p;
+      bool found_backend_address = false;
+      for (size_t i = 0; i < addresses->num_addresses; ++i) {
+        if (!addresses->addresses[i].is_balancer) {
+          found_backend_address = true;
+          break;
+        }
       }
-    }
-    if (!found_backend_address) {
-      if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
-        gpr_log(GPR_INFO,
-                "resolver requested LB policy %s but provided only balancer "
-                "addresses, no backend addresses -- forcing use of grpclb LB "
-                "policy",
-                (lb_policy_name == NULL ? "(none)" : lb_policy_name));
+      if (!found_backend_address) {
+        if (lb_policy_name != NULL && strcmp(lb_policy_name, "grpclb") != 0) {
+          gpr_log(GPR_INFO,
+                  "resolver requested LB policy %s but provided only balancer "
+                  "addresses, no backend addresses -- forcing use of grpclb LB "
+                  "policy",
+                  lb_policy_name);
+        }
+        lb_policy_name = "grpclb";
       }
-      lb_policy_name = "grpclb";
     }
     // Use pick_first if nothing was specified and we didn't select grpclb
     // above.
@@ -274,15 +281,15 @@ static void on_resolver_result_changed(grpc_exec_ctx *exec_ctx, void *arg,
       state =
           grpc_lb_policy_check_connectivity(exec_ctx, lb_policy, &state_error);
     }
-    const grpc_arg *channel_arg = grpc_channel_args_find(
-        lb_policy_args.additional_args, GRPC_ARG_SERVICE_CONFIG);
+    channel_arg =
+        grpc_channel_args_find(lb_policy_args.args, GRPC_ARG_SERVICE_CONFIG);
     if (channel_arg != NULL) {
       GPR_ASSERT(channel_arg->type == GRPC_ARG_POINTER);
       method_params_table = grpc_method_config_table_convert(
           (grpc_method_config_table *)channel_arg->value.pointer.p,
           method_config_convert_value, &method_parameters_vtable);
     }
-    grpc_resolver_result_unref(exec_ctx, chand->resolver_result);
+    grpc_channel_args_destroy(chand->resolver_result);
     chand->resolver_result = NULL;
   }
 
diff --git a/src/core/ext/client_channel/client_channel_factory.c b/src/core/ext/client_channel/client_channel_factory.c
index db1cc9093c6de0d496184b1ed96b5cf473cf57a6..4900832d5734e813a9c491fd12572d18640006fe 100644
--- a/src/core/ext/client_channel/client_channel_factory.c
+++ b/src/core/ext/client_channel/client_channel_factory.c
@@ -44,14 +44,14 @@ void grpc_client_channel_factory_unref(grpc_exec_ctx* exec_ctx,
 
 grpc_subchannel* grpc_client_channel_factory_create_subchannel(
     grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
-    grpc_subchannel_args* args) {
+    const grpc_subchannel_args* args) {
   return factory->vtable->create_subchannel(exec_ctx, factory, args);
 }
 
 grpc_channel* grpc_client_channel_factory_create_channel(
     grpc_exec_ctx* exec_ctx, grpc_client_channel_factory* factory,
     const char* target, grpc_client_channel_type type,
-    grpc_channel_args* args) {
+    const grpc_channel_args* args) {
   return factory->vtable->create_client_channel(exec_ctx, factory, target, type,
                                                 args);
 }
diff --git a/src/core/ext/client_channel/client_channel_factory.h b/src/core/ext/client_channel/client_channel_factory.h
index 28828c2eb606fee61abbfb50dc3a3f18e8a30880..2b8fc577b3b67f3873d2c3fb0034a460b7a9bb4b 100644
--- a/src/core/ext/client_channel/client_channel_factory.h
+++ b/src/core/ext/client_channel/client_channel_factory.h
@@ -60,12 +60,12 @@ struct grpc_client_channel_factory_vtable {
   void (*unref)(grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory);
   grpc_subchannel *(*create_subchannel)(grpc_exec_ctx *exec_ctx,
                                         grpc_client_channel_factory *factory,
-                                        grpc_subchannel_args *args);
+                                        const grpc_subchannel_args *args);
   grpc_channel *(*create_client_channel)(grpc_exec_ctx *exec_ctx,
                                          grpc_client_channel_factory *factory,
                                          const char *target,
                                          grpc_client_channel_type type,
-                                         grpc_channel_args *args);
+                                         const grpc_channel_args *args);
 };
 
 void grpc_client_channel_factory_ref(grpc_client_channel_factory *factory);
@@ -75,11 +75,12 @@ void grpc_client_channel_factory_unref(grpc_exec_ctx *exec_ctx,
 /** Create a new grpc_subchannel */
 grpc_subchannel *grpc_client_channel_factory_create_subchannel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
-    grpc_subchannel_args *args);
+    const grpc_subchannel_args *args);
 
 /** Create a new grpc_channel */
 grpc_channel *grpc_client_channel_factory_create_channel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *factory,
-    const char *target, grpc_client_channel_type type, grpc_channel_args *args);
+    const char *target, grpc_client_channel_type type,
+    const grpc_channel_args *args);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_CLIENT_CHANNEL_FACTORY_H */
diff --git a/src/core/ext/client_channel/lb_policy_factory.c b/src/core/ext/client_channel/lb_policy_factory.c
index 45753e69420d41e6b93f06303c4db4ecea61b0df..8a474c881854fb968a68f5140b4e57f1fdd2b007 100644
--- a/src/core/ext/client_channel/lb_policy_factory.c
+++ b/src/core/ext/client_channel/lb_policy_factory.c
@@ -38,19 +38,20 @@
 
 #include "src/core/ext/client_channel/lb_policy_factory.h"
 
-grpc_lb_addresses* grpc_lb_addresses_create(size_t num_addresses) {
+grpc_lb_addresses* grpc_lb_addresses_create(
+    size_t num_addresses, const grpc_lb_user_data_vtable* user_data_vtable) {
   grpc_lb_addresses* addresses = gpr_malloc(sizeof(grpc_lb_addresses));
   addresses->num_addresses = num_addresses;
+  addresses->user_data_vtable = user_data_vtable;
   const size_t addresses_size = sizeof(grpc_lb_address) * num_addresses;
   addresses->addresses = gpr_malloc(addresses_size);
   memset(addresses->addresses, 0, addresses_size);
   return addresses;
 }
 
-grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses,
-                                          void* (*user_data_copy)(void*)) {
-  grpc_lb_addresses* new_addresses =
-      grpc_lb_addresses_create(addresses->num_addresses);
+grpc_lb_addresses* grpc_lb_addresses_copy(const grpc_lb_addresses* addresses) {
+  grpc_lb_addresses* new_addresses = grpc_lb_addresses_create(
+      addresses->num_addresses, addresses->user_data_vtable);
   memcpy(new_addresses->addresses, addresses->addresses,
          sizeof(grpc_lb_address) * addresses->num_addresses);
   for (size_t i = 0; i < addresses->num_addresses; ++i) {
@@ -58,9 +59,9 @@ grpc_lb_addresses* grpc_lb_addresses_copy(grpc_lb_addresses* addresses,
       new_addresses->addresses[i].balancer_name =
           gpr_strdup(new_addresses->addresses[i].balancer_name);
     }
-    if (user_data_copy != NULL) {
-      new_addresses->addresses[i].user_data =
-          user_data_copy(new_addresses->addresses[i].user_data);
+    if (new_addresses->addresses[i].user_data != NULL) {
+      new_addresses->addresses[i].user_data = addresses->user_data_vtable->copy(
+          new_addresses->addresses[i].user_data);
     }
   }
   return new_addresses;
@@ -71,6 +72,7 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
                                    bool is_balancer, char* balancer_name,
                                    void* user_data) {
   GPR_ASSERT(index < addresses->num_addresses);
+  if (user_data != NULL) GPR_ASSERT(addresses->user_data_vtable != NULL);
   grpc_lb_address* target = &addresses->addresses[index];
   memcpy(target->address.addr, address, address_len);
   target->address.len = address_len;
@@ -79,18 +81,70 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses* addresses, size_t index,
   target->user_data = user_data;
 }
 
-void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses,
-                               void (*user_data_destroy)(void*)) {
+int grpc_lb_addresses_cmp(const grpc_lb_addresses* addresses1,
+                          const grpc_lb_addresses* addresses2) {
+  if (addresses1->num_addresses > addresses2->num_addresses) return 1;
+  if (addresses1->num_addresses < addresses2->num_addresses) return -1;
+  if (addresses1->user_data_vtable > addresses2->user_data_vtable) return 1;
+  if (addresses1->user_data_vtable < addresses2->user_data_vtable) return -1;
+  for (size_t i = 0; i < addresses1->num_addresses; ++i) {
+    const grpc_lb_address* target1 = &addresses1->addresses[i];
+    const grpc_lb_address* target2 = &addresses2->addresses[i];
+    if (target1->address.len > target2->address.len) return 1;
+    if (target1->address.len < target2->address.len) return -1;
+    int retval = memcmp(target1->address.addr, target2->address.addr,
+                        target1->address.len);
+    if (retval != 0) return retval;
+    if (target1->is_balancer > target2->is_balancer) return 1;
+    if (target1->is_balancer < target2->is_balancer) return -1;
+    const char* balancer_name1 =
+        target1->balancer_name != NULL ? target1->balancer_name : "";
+    const char* balancer_name2 =
+        target2->balancer_name != NULL ? target2->balancer_name : "";
+    retval = strcmp(balancer_name1, balancer_name2);
+    if (retval != 0) return retval;
+    if (addresses1->user_data_vtable != NULL) {
+      retval = addresses1->user_data_vtable->cmp(target1->user_data,
+                                                 target2->user_data);
+      if (retval != 0) return retval;
+    }
+  }
+  return 0;
+}
+
+void grpc_lb_addresses_destroy(grpc_lb_addresses* addresses) {
   for (size_t i = 0; i < addresses->num_addresses; ++i) {
     gpr_free(addresses->addresses[i].balancer_name);
-    if (user_data_destroy != NULL) {
-      user_data_destroy(addresses->addresses[i].user_data);
+    if (addresses->addresses[i].user_data != NULL) {
+      addresses->user_data_vtable->destroy(addresses->addresses[i].user_data);
     }
   }
   gpr_free(addresses->addresses);
   gpr_free(addresses);
 }
 
+static void* lb_addresses_copy(void* addresses) {
+  return grpc_lb_addresses_copy(addresses);
+}
+static void lb_addresses_destroy(void* addresses) {
+  grpc_lb_addresses_destroy(addresses);
+}
+static int lb_addresses_cmp(void* addresses1, void* addresses2) {
+  return grpc_lb_addresses_cmp(addresses1, addresses2);
+}
+static const grpc_arg_pointer_vtable lb_addresses_arg_vtable = {
+    lb_addresses_copy, lb_addresses_destroy, lb_addresses_cmp};
+
+grpc_arg grpc_lb_addresses_create_channel_arg(
+    const grpc_lb_addresses* addresses) {
+  grpc_arg arg;
+  arg.type = GRPC_ARG_POINTER;
+  arg.key = GRPC_ARG_LB_ADDRESSES;
+  arg.value.pointer.p = (void*)addresses;
+  arg.value.pointer.vtable = &lb_addresses_arg_vtable;
+  return arg;
+}
+
 void grpc_lb_policy_factory_ref(grpc_lb_policy_factory* factory) {
   factory->vtable->ref(factory);
 }
diff --git a/src/core/ext/client_channel/lb_policy_factory.h b/src/core/ext/client_channel/lb_policy_factory.h
index 3e53972445fb78e03436dd8d5b8eb94db9862054..e2b8080a32917461c003b73930b55df6d669ab64 100644
--- a/src/core/ext/client_channel/lb_policy_factory.h
+++ b/src/core/ext/client_channel/lb_policy_factory.h
@@ -59,19 +59,26 @@ typedef struct grpc_lb_address {
   void *user_data;
 } grpc_lb_address;
 
+typedef struct grpc_lb_user_data_vtable {
+  void *(*copy)(void *);
+  void (*destroy)(void *);
+  int (*cmp)(void *, void *);
+} grpc_lb_user_data_vtable;
+
 typedef struct grpc_lb_addresses {
   size_t num_addresses;
   grpc_lb_address *addresses;
+  const grpc_lb_user_data_vtable *user_data_vtable;
 } grpc_lb_addresses;
 
 /** Returns a grpc_addresses struct with enough space for
- * \a num_addresses addresses. */
-grpc_lb_addresses *grpc_lb_addresses_create(size_t num_addresses);
+    \a num_addresses addresses.  The \a user_data_vtable argument may be
+    NULL if no user data will be added. */
+grpc_lb_addresses *grpc_lb_addresses_create(
+    size_t num_addresses, const grpc_lb_user_data_vtable *user_data_vtable);
 
-/** Creates a copy of \a addresses.  If \a user_data_copy is not NULL,
- * it will be invoked to copy the \a user_data field of each address. */
-grpc_lb_addresses *grpc_lb_addresses_copy(grpc_lb_addresses *addresses,
-                                          void *(*user_data_copy)(void *));
+/** Creates a copy of \a addresses. */
+grpc_lb_addresses *grpc_lb_addresses_copy(const grpc_lb_addresses *addresses);
 
 /** Sets the value of the address at index \a index of \a addresses.
  * \a address is a socket address of length \a address_len.
@@ -81,20 +88,21 @@ void grpc_lb_addresses_set_address(grpc_lb_addresses *addresses, size_t index,
                                    bool is_balancer, char *balancer_name,
                                    void *user_data);
 
-/** Destroys \a addresses.  If \a user_data_destroy is not NULL, it will
- * be invoked to destroy the \a user_data field of each address. */
-void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses,
-                               void (*user_data_destroy)(void *));
+/** Compares \a addresses1 and \a addresses2. */
+int grpc_lb_addresses_cmp(const grpc_lb_addresses *addresses1,
+                          const grpc_lb_addresses *addresses2);
+
+/** Destroys \a addresses. */
+void grpc_lb_addresses_destroy(grpc_lb_addresses *addresses);
+
+/** Returns a channel arg containing \a addresses. */
+grpc_arg grpc_lb_addresses_create_channel_arg(
+    const grpc_lb_addresses *addresses);
 
 /** Arguments passed to LB policies. */
-/* TODO(roth, ctiller): Consider replacing this struct with
-   grpc_channel_args.  See comment in resolver_result.h for details. */
 typedef struct grpc_lb_policy_args {
-  const char *server_name;
-  grpc_lb_addresses *addresses;
   grpc_client_channel_factory *client_channel_factory;
-  /* Can be used to pass implementation-specific parameters to the LB policy. */
-  grpc_channel_args *additional_args;
+  grpc_channel_args *args;
 } grpc_lb_policy_args;
 
 struct grpc_lb_policy_factory_vtable {
diff --git a/src/core/ext/client_channel/resolver.c b/src/core/ext/client_channel/resolver.c
index 0c26d95f2f1533b51e40931d43b382880d7cde92..2ae4fe862e97b4337c19fbfacf7fcbaf0d54c6cc 100644
--- a/src/core/ext/client_channel/resolver.c
+++ b/src/core/ext/client_channel/resolver.c
@@ -76,7 +76,6 @@ void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
 }
 
 void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                        grpc_resolver_result **result,
-                        grpc_closure *on_complete) {
+                        grpc_channel_args **result, grpc_closure *on_complete) {
   resolver->vtable->next(exec_ctx, resolver, result, on_complete);
 }
diff --git a/src/core/ext/client_channel/resolver.h b/src/core/ext/client_channel/resolver.h
index 0951613175a642b1569918f641dc5de6c506b8c8..96ece92b9d82e30f25f9591cfe905014dad5515a 100644
--- a/src/core/ext/client_channel/resolver.h
+++ b/src/core/ext/client_channel/resolver.h
@@ -34,15 +34,13 @@
 #ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H
 #define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H
 
-#include "src/core/ext/client_channel/resolver_result.h"
 #include "src/core/ext/client_channel/subchannel.h"
 #include "src/core/lib/iomgr/iomgr.h"
 
 typedef struct grpc_resolver grpc_resolver;
 typedef struct grpc_resolver_vtable grpc_resolver_vtable;
 
-/** grpc_resolver provides grpc_resolver_result objects to grpc_channel
-    objects */
+/** \a grpc_resolver provides \a grpc_channel_args objects to its caller */
 struct grpc_resolver {
   const grpc_resolver_vtable *vtable;
   gpr_refcount refs;
@@ -53,7 +51,7 @@ struct grpc_resolver_vtable {
   void (*shutdown)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
   void (*channel_saw_error)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
   void (*next)(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-               grpc_resolver_result **result, grpc_closure *on_complete);
+               grpc_channel_args **result, grpc_closure *on_complete);
 };
 
 #ifdef GRPC_RESOLVER_REFCOUNT_DEBUG
@@ -81,14 +79,12 @@ void grpc_resolver_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver);
 void grpc_resolver_channel_saw_error(grpc_exec_ctx *exec_ctx,
                                      grpc_resolver *resolver);
 
-/** Get the next client config. Called by the channel to fetch a new
-    configuration. Expected to set *result with a new configuration,
-    and then schedule on_complete for execution.
+/** Get the next result from the resolver.  Expected to set \a *result with
+    new channel args and then schedule \a on_complete for execution.
 
-    If resolution is fatally broken, set *result to NULL and
-    schedule on_complete. */
+    If resolution is fatally broken, set \a *result to NULL and
+    schedule \a on_complete. */
 void grpc_resolver_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                        grpc_resolver_result **result,
-                        grpc_closure *on_complete);
+                        grpc_channel_args **result, grpc_closure *on_complete);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_H */
diff --git a/src/core/ext/client_channel/resolver_factory.h b/src/core/ext/client_channel/resolver_factory.h
index 1ad018ce1fe8e0c401d9726d84802e47f5d48f73..4da42e84d2f23c2887984b177dfe0282360dd2ce 100644
--- a/src/core/ext/client_channel/resolver_factory.h
+++ b/src/core/ext/client_channel/resolver_factory.h
@@ -41,13 +41,14 @@
 typedef struct grpc_resolver_factory grpc_resolver_factory;
 typedef struct grpc_resolver_factory_vtable grpc_resolver_factory_vtable;
 
-/** grpc_resolver provides grpc_resolver_result objects to grpc_channel
-    objects */
 struct grpc_resolver_factory {
   const grpc_resolver_factory_vtable *vtable;
 };
 
-typedef struct grpc_resolver_args { grpc_uri *uri; } grpc_resolver_args;
+typedef struct grpc_resolver_args {
+  grpc_uri *uri;
+  const grpc_channel_args *args;
+} grpc_resolver_args;
 
 struct grpc_resolver_factory_vtable {
   void (*ref)(grpc_resolver_factory *factory);
diff --git a/src/core/ext/client_channel/resolver_registry.c b/src/core/ext/client_channel/resolver_registry.c
index ee43329874620c831d1ff8477207a9b1abfa75ec..d0f0fc3f332f012582490d57049dde65f79cd188 100644
--- a/src/core/ext/client_channel/resolver_registry.c
+++ b/src/core/ext/client_channel/resolver_registry.c
@@ -131,14 +131,16 @@ static grpc_resolver_factory *resolve_factory(const char *target,
   return factory;
 }
 
-grpc_resolver *grpc_resolver_create(const char *target) {
+grpc_resolver *grpc_resolver_create(const char *target,
+                                    const grpc_channel_args *args) {
   grpc_uri *uri = NULL;
   grpc_resolver_factory *factory = resolve_factory(target, &uri);
   grpc_resolver *resolver;
-  grpc_resolver_args args;
-  memset(&args, 0, sizeof(args));
-  args.uri = uri;
-  resolver = grpc_resolver_factory_create_resolver(factory, &args);
+  grpc_resolver_args resolver_args;
+  memset(&resolver_args, 0, sizeof(resolver_args));
+  resolver_args.uri = uri;
+  resolver_args.args = args;
+  resolver = grpc_resolver_factory_create_resolver(factory, &resolver_args);
   grpc_uri_destroy(uri);
   return resolver;
 }
diff --git a/src/core/ext/client_channel/resolver_registry.h b/src/core/ext/client_channel/resolver_registry.h
index 0a39d4a1878194dc41beaa76acb2807e8cd34246..2a95a669f0d47a988b2ca8e5ec7b79b0d232bd21 100644
--- a/src/core/ext/client_channel/resolver_registry.h
+++ b/src/core/ext/client_channel/resolver_registry.h
@@ -57,8 +57,11 @@ void grpc_register_resolver_type(grpc_resolver_factory *factory);
     was not NULL).
     If a resolver factory was found, use it to instantiate a resolver and
     return it.
-    If a resolver factory was not found, return NULL. */
-grpc_resolver *grpc_resolver_create(const char *target);
+    If a resolver factory was not found, return NULL.
+    \a args is a set of channel arguments to be included in the result
+    (typically the set of arguments passed in from the client API). */
+grpc_resolver *grpc_resolver_create(const char *target,
+                                    const grpc_channel_args *args);
 
 /** Find a resolver factory given a name and return an (owned-by-the-caller)
  *  reference to it */
diff --git a/src/core/ext/client_channel/resolver_result.c b/src/core/ext/client_channel/resolver_result.c
deleted file mode 100644
index ab1c215955b56dc6001986e78727184d15cd213f..0000000000000000000000000000000000000000
--- a/src/core/ext/client_channel/resolver_result.c
+++ /dev/null
@@ -1,94 +0,0 @@
-//
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#include "src/core/ext/client_channel/resolver_result.h"
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/string_util.h>
-
-#include "src/core/lib/channel/channel_args.h"
-
-struct grpc_resolver_result {
-  gpr_refcount refs;
-  char* server_name;
-  grpc_lb_addresses* addresses;
-  char* lb_policy_name;
-  grpc_channel_args* lb_policy_args;
-};
-
-grpc_resolver_result* grpc_resolver_result_create(
-    const char* server_name, grpc_lb_addresses* addresses,
-    const char* lb_policy_name, grpc_channel_args* lb_policy_args) {
-  grpc_resolver_result* result = gpr_malloc(sizeof(*result));
-  memset(result, 0, sizeof(*result));
-  gpr_ref_init(&result->refs, 1);
-  result->server_name = gpr_strdup(server_name);
-  result->addresses = addresses;
-  result->lb_policy_name = gpr_strdup(lb_policy_name);
-  result->lb_policy_args = lb_policy_args;
-  return result;
-}
-
-void grpc_resolver_result_ref(grpc_resolver_result* result) {
-  gpr_ref(&result->refs);
-}
-
-void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
-                                grpc_resolver_result* result) {
-  if (gpr_unref(&result->refs)) {
-    gpr_free(result->server_name);
-    grpc_lb_addresses_destroy(result->addresses, NULL /* user_data_destroy */);
-    gpr_free(result->lb_policy_name);
-    grpc_channel_args_destroy(result->lb_policy_args);
-    gpr_free(result);
-  }
-}
-
-const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result) {
-  return result->server_name;
-}
-
-grpc_lb_addresses* grpc_resolver_result_get_addresses(
-    grpc_resolver_result* result) {
-  return result->addresses;
-}
-
-const char* grpc_resolver_result_get_lb_policy_name(
-    grpc_resolver_result* result) {
-  return result->lb_policy_name;
-}
-
-grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
-    grpc_resolver_result* result) {
-  return result->lb_policy_args;
-}
diff --git a/src/core/ext/client_channel/resolver_result.h b/src/core/ext/client_channel/resolver_result.h
deleted file mode 100644
index 5421fd9470591d280d73852f9fae12e8e37f3ef8..0000000000000000000000000000000000000000
--- a/src/core/ext/client_channel/resolver_result.h
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright 2015, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-
-#ifndef GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
-#define GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H
-
-#include "src/core/ext/client_channel/lb_policy_factory.h"
-
-// TODO(roth, ctiller): In the long term, we are considering replacing
-// the resolver_result data structure with grpc_channel_args.  The idea is
-// that the resolver will return a set of channel args that contains the
-// information that is currently in the resolver_result struct.  For
-// example, there will be specific args indicating the set of addresses
-// and the name of the LB policy to instantiate.  Note that if we did
-// this, we would probably want to change the data structure of
-// grpc_channel_args such to a hash table or AVL or some other data
-// structure that does not require linear search to find keys.
-
-/// Results reported from a grpc_resolver.
-typedef struct grpc_resolver_result grpc_resolver_result;
-
-/// Takes ownership of \a addresses and \a lb_policy_args.
-grpc_resolver_result* grpc_resolver_result_create(
-    const char* server_name, grpc_lb_addresses* addresses,
-    const char* lb_policy_name, grpc_channel_args* lb_policy_args);
-
-void grpc_resolver_result_ref(grpc_resolver_result* result);
-void grpc_resolver_result_unref(grpc_exec_ctx* exec_ctx,
-                                grpc_resolver_result* result);
-
-/// Accessors.  Caller does NOT take ownership of results.
-const char* grpc_resolver_result_get_server_name(grpc_resolver_result* result);
-grpc_lb_addresses* grpc_resolver_result_get_addresses(
-    grpc_resolver_result* result);
-const char* grpc_resolver_result_get_lb_policy_name(
-    grpc_resolver_result* result);
-grpc_channel_args* grpc_resolver_result_get_lb_policy_args(
-    grpc_resolver_result* result);
-
-#endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_RESOLVER_RESULT_H */
diff --git a/src/core/ext/client_channel/subchannel.c b/src/core/ext/client_channel/subchannel.c
index 157f78877f82353b8901b31ff9a4332f4f7a5ae6..ab6aede23ac6322e3222c461159a489cd32a33dd 100644
--- a/src/core/ext/client_channel/subchannel.c
+++ b/src/core/ext/client_channel/subchannel.c
@@ -297,7 +297,7 @@ void grpc_subchannel_weak_unref(grpc_exec_ctx *exec_ctx,
 
 grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
                                         grpc_connector *connector,
-                                        grpc_subchannel_args *args) {
+                                        const grpc_subchannel_args *args) {
   grpc_subchannel_key *key = grpc_subchannel_key_create(connector, args);
   grpc_subchannel *c = grpc_subchannel_index_find(exec_ctx, key);
   if (c) {
diff --git a/src/core/ext/client_channel/subchannel.h b/src/core/ext/client_channel/subchannel.h
index 0350d5574ca6ca1120e9c951ed83aeded0e052f5..565207407410396dd43a5b8c5671c10c8468c7cf 100644
--- a/src/core/ext/client_channel/subchannel.h
+++ b/src/core/ext/client_channel/subchannel.h
@@ -173,6 +173,6 @@ struct grpc_subchannel_args {
 /** create a subchannel given a connector */
 grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
                                         grpc_connector *connector,
-                                        grpc_subchannel_args *args);
+                                        const grpc_subchannel_args *args);
 
 #endif /* GRPC_CORE_EXT_CLIENT_CHANNEL_SUBCHANNEL_H */
diff --git a/src/core/ext/client_channel/subchannel_index.c b/src/core/ext/client_channel/subchannel_index.c
index 7933760e0efba6410009430c65cf4b937562a227..227013a7d78e144e704f4c1ab1fd7525e2a38c81 100644
--- a/src/core/ext/client_channel/subchannel_index.c
+++ b/src/core/ext/client_channel/subchannel_index.c
@@ -73,7 +73,7 @@ static grpc_exec_ctx *current_ctx() {
 }
 
 static grpc_subchannel_key *create_key(
-    grpc_connector *connector, grpc_subchannel_args *args,
+    grpc_connector *connector, const grpc_subchannel_args *args,
     grpc_channel_args *(*copy_channel_args)(const grpc_channel_args *args)) {
   grpc_subchannel_key *k = gpr_malloc(sizeof(*k));
   k->connector = grpc_connector_ref(connector);
@@ -96,8 +96,8 @@ static grpc_subchannel_key *create_key(
   return k;
 }
 
-grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *connector,
-                                                grpc_subchannel_args *args) {
+grpc_subchannel_key *grpc_subchannel_key_create(
+    grpc_connector *connector, const grpc_subchannel_args *args) {
   return create_key(connector, args, grpc_channel_args_normalize);
 }
 
diff --git a/src/core/ext/client_channel/subchannel_index.h b/src/core/ext/client_channel/subchannel_index.h
index 5b3af6b05463fe1d398083911c52fbacdc993998..a67bd5e2195deaf7684c4997a58747259a05c824 100644
--- a/src/core/ext/client_channel/subchannel_index.h
+++ b/src/core/ext/client_channel/subchannel_index.h
@@ -43,8 +43,8 @@
 typedef struct grpc_subchannel_key grpc_subchannel_key;
 
 /** Create a key that can be used to uniquely identify a subchannel */
-grpc_subchannel_key *grpc_subchannel_key_create(grpc_connector *con,
-                                                grpc_subchannel_args *args);
+grpc_subchannel_key *grpc_subchannel_key_create(
+    grpc_connector *con, const grpc_subchannel_args *args);
 
 /** Destroy a subchannel key */
 void grpc_subchannel_key_destroy(grpc_exec_ctx *exec_ctx,
diff --git a/src/core/ext/lb_policy/grpclb/grpclb.c b/src/core/ext/lb_policy/grpclb/grpclb.c
index 36f0a90bb869ca313dd5d77753b6572a3de56108..6da4febf266cb986de785ea4d443b65eeb196d02 100644
--- a/src/core/ext/lb_policy/grpclb/grpclb.c
+++ b/src/core/ext/lb_policy/grpclb/grpclb.c
@@ -343,6 +343,21 @@ static bool is_server_valid(const grpc_grpclb_server *server, size_t idx,
   return true;
 }
 
+/* vtable for LB tokens in grpc_lb_addresses. */
+static void *lb_token_copy(void *token) {
+  return token == NULL ? NULL : GRPC_MDELEM_REF(token);
+}
+static void lb_token_destroy(void *token) {
+  if (token != NULL) GRPC_MDELEM_UNREF(token);
+}
+static int lb_token_cmp(void *token1, void *token2) {
+  if (token1 > token2) return 1;
+  if (token1 < token2) return -1;
+  return 0;
+}
+static const grpc_lb_user_data_vtable lb_token_vtable = {
+    lb_token_copy, lb_token_destroy, lb_token_cmp};
+
 /* Returns addresses extracted from \a serverlist. */
 static grpc_lb_addresses *process_serverlist(
     const grpc_grpclb_serverlist *serverlist) {
@@ -354,7 +369,8 @@ static grpc_lb_addresses *process_serverlist(
   }
   if (num_valid == 0) return NULL;
 
-  grpc_lb_addresses *lb_addresses = grpc_lb_addresses_create(num_valid);
+  grpc_lb_addresses *lb_addresses =
+      grpc_lb_addresses_create(num_valid, &lb_token_vtable);
 
   /* second pass: actually populate the addresses and LB tokens (aka user data
    * to the outside world) to be read by the RR policy during its creation.
@@ -415,11 +431,6 @@ static grpc_lb_addresses *process_serverlist(
   return lb_addresses;
 }
 
-/* A plugin for grpc_lb_addresses_destroy that unrefs the LB token metadata. */
-static void lb_token_destroy(void *token) {
-  if (token != NULL) GRPC_MDELEM_UNREF(token);
-}
-
 /* perform a pick over \a rr_policy. Given that a pick can return immediately
  * (ignoring its completion callback) we need to perform the cleanups this
  * callback would be otherwise resposible for */
@@ -459,20 +470,27 @@ static grpc_lb_policy *create_rr_locked(
     glb_lb_policy *glb_policy) {
   GPR_ASSERT(serverlist != NULL && serverlist->num_servers > 0);
 
+  if (glb_policy->addresses != NULL) {
+    /* dispose of the previous version */
+    grpc_lb_addresses_destroy(glb_policy->addresses);
+  }
+  glb_policy->addresses = process_serverlist(serverlist);
+
   grpc_lb_policy_args args;
   memset(&args, 0, sizeof(args));
-  args.server_name = glb_policy->server_name;
   args.client_channel_factory = glb_policy->cc_factory;
-  args.addresses = process_serverlist(serverlist);
-  args.additional_args = glb_policy->args;
 
-  grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
+  // Replace the LB addresses in the channel args that we pass down to
+  // the subchannel.
+  static const char *keys_to_remove[] = {GRPC_ARG_LB_ADDRESSES};
+  const grpc_arg arg =
+      grpc_lb_addresses_create_channel_arg(glb_policy->addresses);
+  args.args = grpc_channel_args_copy_and_add_and_remove(
+      glb_policy->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove), &arg,
+      1);
 
-  if (glb_policy->addresses != NULL) {
-    /* dispose of the previous version */
-    grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
-  }
-  glb_policy->addresses = args.addresses;
+  grpc_lb_policy *rr = grpc_lb_policy_create(exec_ctx, "round_robin", &args);
+  grpc_channel_args_destroy(args.args);
 
   return rr;
 }
@@ -568,6 +586,12 @@ static void glb_rr_connectivity_changed(grpc_exec_ctx *exec_ctx, void *arg,
 static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
                                   grpc_lb_policy_factory *factory,
                                   grpc_lb_policy_args *args) {
+  /* Get server name. */
+  const grpc_arg *arg =
+      grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
+  const char *server_name =
+      arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
+
   /* Count the number of gRPC-LB addresses. There must be at least one.
    * TODO(roth): For now, we ignore non-balancer addresses, but in the
    * future, we may change the behavior such that we fall back to using
@@ -575,24 +599,27 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
    * time, this should be changed to allow a list with no balancer addresses,
    * since the resolver might fail to return a balancer address even when
    * this is the right LB policy to use. */
+  arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
+  GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
+  grpc_lb_addresses *addresses = arg->value.pointer.p;
   size_t num_grpclb_addrs = 0;
-  for (size_t i = 0; i < args->addresses->num_addresses; ++i) {
-    if (args->addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
+  for (size_t i = 0; i < addresses->num_addresses; ++i) {
+    if (addresses->addresses[i].is_balancer) ++num_grpclb_addrs;
   }
   if (num_grpclb_addrs == 0) return NULL;
 
   glb_lb_policy *glb_policy = gpr_malloc(sizeof(*glb_policy));
   memset(glb_policy, 0, sizeof(*glb_policy));
 
-  /* All input addresses in args->addresses come from a resolver that claims
+  /* All input addresses in addresses come from a resolver that claims
    * they are LB services. It's the resolver's responsibility to make sure
    * this
    * policy is only instantiated and used in that case.
    *
    * Create a client channel over them to communicate with a LB service */
-  glb_policy->server_name = gpr_strdup(args->server_name);
+  glb_policy->server_name = gpr_strdup(server_name);
   glb_policy->cc_factory = args->client_channel_factory;
-  glb_policy->args = grpc_channel_args_copy(args->additional_args);
+  glb_policy->args = grpc_channel_args_copy(args->args);
   GPR_ASSERT(glb_policy->cc_factory != NULL);
 
   /* construct a target from the addresses in args, given in the form
@@ -600,19 +627,19 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
    * TODO(dgq): support mixed ip version */
   char **addr_strs = gpr_malloc(sizeof(char *) * num_grpclb_addrs);
   size_t addr_index = 0;
-  for (size_t i = 0; i < args->addresses->num_addresses; i++) {
-    if (args->addresses->addresses[i].user_data != NULL) {
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
+    if (addresses->addresses[i].user_data != NULL) {
       gpr_log(GPR_ERROR,
               "This LB policy doesn't support user data. It will be ignored");
     }
-    if (args->addresses->addresses[i].is_balancer) {
+    if (addresses->addresses[i].is_balancer) {
       if (addr_index == 0) {
         addr_strs[addr_index++] =
-            grpc_sockaddr_to_uri(&args->addresses->addresses[i].address);
+            grpc_sockaddr_to_uri(&addresses->addresses[i].address);
       } else {
-        GPR_ASSERT(grpc_sockaddr_to_string(
-                       &addr_strs[addr_index++],
-                       &args->addresses->addresses[i].address, true) > 0);
+        GPR_ASSERT(grpc_sockaddr_to_string(&addr_strs[addr_index++],
+                                           &addresses->addresses[i].address,
+                                           true) > 0);
       }
     }
   }
@@ -620,10 +647,29 @@ static grpc_lb_policy *glb_create(grpc_exec_ctx *exec_ctx,
   char *target_uri_str = gpr_strjoin_sep((const char **)addr_strs,
                                          num_grpclb_addrs, ",", &uri_path_len);
 
-  /* will pick using pick_first */
+  /* Create a channel to talk to the LBs.
+   *
+   * We strip out the channel arg for the LB policy name, since we want
+   * to use the default (pick_first) in this case.
+   *
+   * We also strip out the channel arg for the resolved addresses, since
+   * that will be generated by the name resolver used in the LB channel.
+   * Note that the LB channel will use the sockaddr resolver, so this
+   * won't actually generate a query to DNS (or some other name service).
+   * However, the addresses returned by the sockaddr resolver will have
+   * is_balancer=false, whereas our own addresses have is_balancer=true.
+   * We need the LB channel to return addresses with is_balancer=false
+   * so that it does not wind up recursively using the grpclb LB policy,
+   * as per the special case logic in client_channel.c.
+   */
+  static const char *keys_to_remove[] = {GRPC_ARG_LB_POLICY_NAME,
+                                         GRPC_ARG_LB_ADDRESSES};
+  grpc_channel_args *new_args = grpc_channel_args_copy_and_remove(
+      args->args, keys_to_remove, GPR_ARRAY_SIZE(keys_to_remove));
   glb_policy->lb_channel = grpc_client_channel_factory_create_channel(
       exec_ctx, glb_policy->cc_factory, target_uri_str,
-      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, NULL);
+      GRPC_CLIENT_CHANNEL_TYPE_LOAD_BALANCING, new_args);
+  grpc_channel_args_destroy(new_args);
 
   gpr_free(target_uri_str);
   for (size_t i = 0; i < num_grpclb_addrs; i++) {
@@ -664,7 +710,7 @@ static void glb_destroy(grpc_exec_ctx *exec_ctx, grpc_lb_policy *pol) {
     grpc_grpclb_destroy_serverlist(glb_policy->serverlist);
   }
   gpr_mu_destroy(&glb_policy->mu);
-  grpc_lb_addresses_destroy(glb_policy->addresses, lb_token_destroy);
+  grpc_lb_addresses_destroy(glb_policy->addresses);
   gpr_free(glb_policy);
 }
 
diff --git a/src/core/ext/lb_policy/pick_first/pick_first.c b/src/core/ext/lb_policy/pick_first/pick_first.c
index 7b53f8813f751fb8d5bff59ed3c158c10f80a4bb..5d3433df74a179c4eaff8f02acaea9829d332e71 100644
--- a/src/core/ext/lb_policy/pick_first/pick_first.c
+++ b/src/core/ext/lb_policy/pick_first/pick_first.c
@@ -34,7 +34,9 @@
 #include <string.h>
 
 #include <grpc/support/alloc.h>
+
 #include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/transport/connectivity_state.h"
 
 typedef struct pending_pick {
@@ -432,14 +434,22 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
 static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
                                          grpc_lb_policy_factory *factory,
                                          grpc_lb_policy_args *args) {
-  GPR_ASSERT(args->addresses != NULL);
   GPR_ASSERT(args->client_channel_factory != NULL);
 
+  /* Get server name. */
+  const grpc_arg *arg =
+      grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
+  const char *server_name =
+      arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
+
   /* Find the number of backend addresses. We ignore balancer
    * addresses, since we don't know how to handle them. */
+  arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
+  GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
+  grpc_lb_addresses *addresses = arg->value.pointer.p;
   size_t num_addrs = 0;
-  for (size_t i = 0; i < args->addresses->num_addresses; i++) {
-    if (!args->addresses->addresses[i].is_balancer) ++num_addrs;
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
+    if (!addresses->addresses[i].is_balancer) ++num_addrs;
   }
   if (num_addrs == 0) return NULL;
 
@@ -450,21 +460,21 @@ static grpc_lb_policy *create_pick_first(grpc_exec_ctx *exec_ctx,
   memset(p->subchannels, 0, sizeof(*p->subchannels) * num_addrs);
   grpc_subchannel_args sc_args;
   size_t subchannel_idx = 0;
-  for (size_t i = 0; i < args->addresses->num_addresses; i++) {
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
     /* Skip balancer addresses, since we only know how to handle backends. */
-    if (args->addresses->addresses[i].is_balancer) continue;
+    if (addresses->addresses[i].is_balancer) continue;
 
-    if (args->addresses->addresses[i].user_data != NULL) {
+    if (addresses->addresses[i].user_data != NULL) {
       gpr_log(GPR_ERROR,
               "This LB policy doesn't support user data. It will be ignored");
     }
 
     memset(&sc_args, 0, sizeof(grpc_subchannel_args));
     /* server_name will be copied as part of the subchannel creation. This makes
-     * the copying of args->server_name (a borrowed pointer) OK. */
-    sc_args.server_name = args->server_name;
-    sc_args.addr = &args->addresses->addresses[i].address;
-    sc_args.args = args->additional_args;
+     * the copying of server_name (a borrowed pointer) OK. */
+    sc_args.server_name = server_name;
+    sc_args.addr = &addresses->addresses[i].address;
+    sc_args.args = args->args;
 
     grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
         exec_ctx, args->client_channel_factory, &sc_args);
diff --git a/src/core/ext/lb_policy/round_robin/round_robin.c b/src/core/ext/lb_policy/round_robin/round_robin.c
index 3073c13e67dff76228d4804c3b09b6ed13a6bf16..c0743b00e8013f7d6d3413f40105227cf15c2e8a 100644
--- a/src/core/ext/lb_policy/round_robin/round_robin.c
+++ b/src/core/ext/lb_policy/round_robin/round_robin.c
@@ -64,6 +64,7 @@
 #include <grpc/support/alloc.h>
 
 #include "src/core/ext/client_channel/lb_policy_registry.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/debug/trace.h"
 #include "src/core/lib/transport/connectivity_state.h"
 #include "src/core/lib/transport/static_metadata.h"
@@ -598,14 +599,22 @@ static void round_robin_factory_unref(grpc_lb_policy_factory *factory) {}
 static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
                                           grpc_lb_policy_factory *factory,
                                           grpc_lb_policy_args *args) {
-  GPR_ASSERT(args->addresses != NULL);
   GPR_ASSERT(args->client_channel_factory != NULL);
 
+  /* Get server name. */
+  const grpc_arg *arg =
+      grpc_channel_args_find(args->args, GRPC_ARG_SERVER_NAME);
+  const char *server_name =
+      arg != NULL && arg->type == GRPC_ARG_STRING ? arg->value.string : NULL;
+
   /* Find the number of backend addresses. We ignore balancer
    * addresses, since we don't know how to handle them. */
+  arg = grpc_channel_args_find(args->args, GRPC_ARG_LB_ADDRESSES);
+  GPR_ASSERT(arg != NULL && arg->type == GRPC_ARG_POINTER);
+  grpc_lb_addresses *addresses = arg->value.pointer.p;
   size_t num_addrs = 0;
-  for (size_t i = 0; i < args->addresses->num_addresses; i++) {
-    if (!args->addresses->addresses[i].is_balancer) ++num_addrs;
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
+    if (!addresses->addresses[i].is_balancer) ++num_addrs;
   }
   if (num_addrs == 0) return NULL;
 
@@ -618,16 +627,16 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
 
   grpc_subchannel_args sc_args;
   size_t subchannel_idx = 0;
-  for (size_t i = 0; i < args->addresses->num_addresses; i++) {
+  for (size_t i = 0; i < addresses->num_addresses; i++) {
     /* Skip balancer addresses, since we only know how to handle backends. */
-    if (args->addresses->addresses[i].is_balancer) continue;
+    if (addresses->addresses[i].is_balancer) continue;
 
     memset(&sc_args, 0, sizeof(grpc_subchannel_args));
     /* server_name will be copied as part of the subchannel creation. This makes
-     * the copying of args->server_name (a borrowed pointer) OK. */
-    sc_args.server_name = args->server_name;
-    sc_args.addr = &args->addresses->addresses[i].address;
-    sc_args.args = args->additional_args;
+     * the copying of server_name (a borrowed pointer) OK. */
+    sc_args.server_name = server_name;
+    sc_args.addr = &addresses->addresses[i].address;
+    sc_args.args = args->args;
 
     grpc_subchannel *subchannel = grpc_client_channel_factory_create_subchannel(
         exec_ctx, args->client_channel_factory, &sc_args);
@@ -639,7 +648,7 @@ static grpc_lb_policy *round_robin_create(grpc_exec_ctx *exec_ctx,
       sd->policy = p;
       sd->index = subchannel_idx;
       sd->subchannel = subchannel;
-      sd->user_data = args->addresses->addresses[i].user_data;
+      sd->user_data = addresses->addresses[i].user_data;
       ++subchannel_idx;
       grpc_closure_init(&sd->connectivity_changed_closure,
                         rr_connectivity_changed, sd);
diff --git a/src/core/ext/resolver/dns/native/dns_resolver.c b/src/core/ext/resolver/dns/native/dns_resolver.c
index b4ceee340e904d80109bbaa90baf478471950ae8..958b8af8b28ee6394db1ce481bc191010e74dac5 100644
--- a/src/core/ext/resolver/dns/native/dns_resolver.c
+++ b/src/core/ext/resolver/dns/native/dns_resolver.c
@@ -40,6 +40,7 @@
 #include "src/core/ext/client_channel/http_connect_handshaker.h"
 #include "src/core/ext/client_channel/lb_policy_registry.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "src/core/lib/support/backoff.h"
@@ -53,12 +54,12 @@
 typedef struct {
   /** base class: must be first */
   grpc_resolver base;
-  /** target name */
-  char *target_name;
-  /** name to resolve (usually the same as target_name) */
+  /** name to resolve */
   char *name_to_resolve;
   /** default port to use */
   char *default_port;
+  /** channel args. */
+  grpc_channel_args *channel_args;
 
   /** mutex guarding the rest of the state */
   gpr_mu mu;
@@ -71,9 +72,9 @@ typedef struct {
   /** pending next completion, or NULL */
   grpc_closure *next_completion;
   /** target result address for next completion */
-  grpc_resolver_result **target_result;
+  grpc_channel_args **target_result;
   /** current (fully resolved) result */
-  grpc_resolver_result *resolved_result;
+  grpc_channel_args *resolved_result;
   /** retry timer */
   bool have_retry_timer;
   grpc_timer retry_timer;
@@ -94,7 +95,7 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
 static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
 static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
 static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                     grpc_resolver_result **target_result,
+                     grpc_channel_args **target_result,
                      grpc_closure *on_complete);
 
 static const grpc_resolver_vtable dns_resolver_vtable = {
@@ -127,7 +128,7 @@ static void dns_channel_saw_error(grpc_exec_ctx *exec_ctx,
 }
 
 static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                     grpc_resolver_result **target_result,
+                     grpc_channel_args **target_result,
                      grpc_closure *on_complete) {
   dns_resolver *r = (dns_resolver *)resolver;
   gpr_mu_lock(&r->mu);
@@ -162,22 +163,23 @@ static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
 static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
                             grpc_error *error) {
   dns_resolver *r = arg;
-  grpc_resolver_result *result = NULL;
+  grpc_channel_args *result = NULL;
   gpr_mu_lock(&r->mu);
   GPR_ASSERT(r->resolving);
   r->resolving = false;
   if (r->addresses != NULL) {
-    grpc_lb_addresses *addresses =
-        grpc_lb_addresses_create(r->addresses->naddrs);
+    grpc_lb_addresses *addresses = grpc_lb_addresses_create(
+        r->addresses->naddrs, NULL /* user_data_vtable */);
     for (size_t i = 0; i < r->addresses->naddrs; ++i) {
       grpc_lb_addresses_set_address(
           addresses, i, &r->addresses->addrs[i].addr,
           r->addresses->addrs[i].len, false /* is_balancer */,
           NULL /* balancer_name */, NULL /* user_data */);
     }
+    grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses);
+    result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
     grpc_resolved_addresses_destroy(r->addresses);
-    result = grpc_resolver_result_create(r->target_name, addresses,
-                                         NULL /* lb_policy_name */, NULL);
+    grpc_lb_addresses_destroy(addresses);
   } else {
     gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
     gpr_timespec next_try = gpr_backoff_step(&r->backoff_state, now);
@@ -197,8 +199,8 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
     grpc_timer_init(exec_ctx, &r->retry_timer, next_try, dns_on_retry_timer, r,
                     now);
   }
-  if (r->resolved_result) {
-    grpc_resolver_result_unref(exec_ctx, r->resolved_result);
+  if (r->resolved_result != NULL) {
+    grpc_channel_args_destroy(r->resolved_result);
   }
   r->resolved_result = result;
   r->resolved_version++;
@@ -222,10 +224,9 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
                                          dns_resolver *r) {
   if (r->next_completion != NULL &&
       r->resolved_version != r->published_version) {
-    *r->target_result = r->resolved_result;
-    if (r->resolved_result) {
-      grpc_resolver_result_ref(r->resolved_result);
-    }
+    *r->target_result = r->resolved_result == NULL
+                            ? NULL
+                            : grpc_channel_args_copy(r->resolved_result);
     grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
     r->published_version = r->resolved_version;
@@ -235,12 +236,12 @@ static void dns_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
 static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
   dns_resolver *r = (dns_resolver *)gr;
   gpr_mu_destroy(&r->mu);
-  if (r->resolved_result) {
-    grpc_resolver_result_unref(exec_ctx, r->resolved_result);
+  if (r->resolved_result != NULL) {
+    grpc_channel_args_destroy(r->resolved_result);
   }
-  gpr_free(r->target_name);
   gpr_free(r->name_to_resolve);
   gpr_free(r->default_port);
+  grpc_channel_args_destroy(r->channel_args);
   gpr_free(r);
 }
 
@@ -260,9 +261,14 @@ static grpc_resolver *dns_create(grpc_resolver_args *args,
   memset(r, 0, sizeof(*r));
   gpr_mu_init(&r->mu);
   grpc_resolver_init(&r->base, &dns_resolver_vtable);
-  r->target_name = gpr_strdup(path);
   r->name_to_resolve = proxy_name == NULL ? gpr_strdup(path) : proxy_name;
   r->default_port = gpr_strdup(default_port);
+  grpc_arg server_name_arg;
+  server_name_arg.type = GRPC_ARG_STRING;
+  server_name_arg.key = GRPC_ARG_SERVER_NAME;
+  server_name_arg.value.string = (char *)path;
+  r->channel_args =
+      grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
   gpr_backoff_init(&r->backoff_state, BACKOFF_MULTIPLIER, BACKOFF_JITTER,
                    BACKOFF_MIN_SECONDS * 1000, BACKOFF_MAX_SECONDS * 1000);
   return &r->base;
diff --git a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
index 6148cbded99948a83a0da7e4ed1cc0974e0c975c..5fec03a8e4192110f1211d447f47a35ce36010f5 100644
--- a/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
+++ b/src/core/ext/resolver/sockaddr/sockaddr_resolver.c
@@ -41,8 +41,10 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/ext/client_channel/lb_policy_factory.h"
 #include "src/core/ext/client_channel/parse_address.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/unix_sockets_posix.h"
 #include "src/core/lib/support/string.h"
@@ -50,10 +52,10 @@
 typedef struct {
   /** base class: must be first */
   grpc_resolver base;
-  /** the path component of the uri passed in */
-  char *target_name;
   /** the addresses that we've 'resolved' */
   grpc_lb_addresses *addresses;
+  /** channel args */
+  grpc_channel_args *channel_args;
   /** mutex guarding the rest of the state */
   gpr_mu mu;
   /** have we published? */
@@ -61,7 +63,7 @@ typedef struct {
   /** pending next completion, or NULL */
   grpc_closure *next_completion;
   /** target result address for next completion */
-  grpc_resolver_result **target_result;
+  grpc_channel_args **target_result;
 } sockaddr_resolver;
 
 static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@@ -73,7 +75,7 @@ static void sockaddr_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
 static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
                                        grpc_resolver *r);
 static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *r,
-                          grpc_resolver_result **target_result,
+                          grpc_channel_args **target_result,
                           grpc_closure *on_complete);
 
 static const grpc_resolver_vtable sockaddr_resolver_vtable = {
@@ -102,7 +104,7 @@ static void sockaddr_channel_saw_error(grpc_exec_ctx *exec_ctx,
 }
 
 static void sockaddr_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
-                          grpc_resolver_result **target_result,
+                          grpc_channel_args **target_result,
                           grpc_closure *on_complete) {
   sockaddr_resolver *r = (sockaddr_resolver *)resolver;
   gpr_mu_lock(&r->mu);
@@ -117,10 +119,9 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
                                               sockaddr_resolver *r) {
   if (r->next_completion != NULL && !r->published) {
     r->published = true;
-    *r->target_result = grpc_resolver_result_create(
-        r->target_name,
-        grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */),
-        NULL /* lb_policy_name */, NULL /* lb_policy_args */);
+    grpc_arg arg = grpc_lb_addresses_create_channel_arg(r->addresses);
+    *r->target_result =
+        grpc_channel_args_copy_and_add(r->channel_args, &arg, 1);
     grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
   }
@@ -129,8 +130,8 @@ static void sockaddr_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
 static void sockaddr_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
   sockaddr_resolver *r = (sockaddr_resolver *)gr;
   gpr_mu_destroy(&r->mu);
-  gpr_free(r->target_name);
-  grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
+  grpc_lb_addresses_destroy(r->addresses);
+  grpc_channel_args_destroy(r->channel_args);
   gpr_free(r);
 }
 
@@ -173,7 +174,8 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args,
   gpr_slice_buffer path_parts;
   gpr_slice_buffer_init(&path_parts);
   gpr_slice_split(path_slice, ",", &path_parts);
-  grpc_lb_addresses *addresses = grpc_lb_addresses_create(path_parts.count);
+  grpc_lb_addresses *addresses =
+      grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
   bool errors_found = false;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_uri ith_uri = *args->uri;
@@ -188,14 +190,19 @@ static grpc_resolver *sockaddr_create(grpc_resolver_args *args,
   gpr_slice_buffer_destroy(&path_parts);
   gpr_slice_unref(path_slice);
   if (errors_found) {
-    grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */);
+    grpc_lb_addresses_destroy(addresses);
     return NULL;
   }
   /* Instantiate resolver. */
   sockaddr_resolver *r = gpr_malloc(sizeof(sockaddr_resolver));
   memset(r, 0, sizeof(*r));
-  r->target_name = gpr_strdup(args->uri->path);
   r->addresses = addresses;
+  grpc_arg server_name_arg;
+  server_name_arg.type = GRPC_ARG_STRING;
+  server_name_arg.key = GRPC_ARG_SERVER_NAME;
+  server_name_arg.value.string = args->uri->path;
+  r->channel_args =
+      grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
   gpr_mu_init(&r->mu);
   grpc_resolver_init(&r->base, &sockaddr_resolver_vtable);
   return &r->base;
diff --git a/src/core/ext/transport/chttp2/client/insecure/channel_create.c b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
index bd9eab8ed198ce716e4182208f940114941685b5..372fb7bf4ca997403594119f351a334e26520367 100644
--- a/src/core/ext/transport/chttp2/client/insecure/channel_create.c
+++ b/src/core/ext/transport/chttp2/client/insecure/channel_create.c
@@ -52,6 +52,10 @@
 #include "src/core/lib/surface/api_trace.h"
 #include "src/core/lib/surface/channel.h"
 
+//
+// connector
+//
+
 typedef struct {
   grpc_connector base;
   gpr_refcount refs;
@@ -156,35 +160,20 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
 static const grpc_connector_vtable connector_vtable = {
     connector_ref, connector_unref, connector_shutdown, connector_connect};
 
-typedef struct {
-  grpc_client_channel_factory base;
-  gpr_refcount refs;
-  grpc_channel_args *merge_args;
-} client_channel_factory;
+//
+// client_channel_factory
+//
 
 static void client_channel_factory_ref(
-    grpc_client_channel_factory *cc_factory) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
-  gpr_ref(&f->refs);
-}
+    grpc_client_channel_factory *cc_factory) {}
 
 static void client_channel_factory_unref(
-    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
-  if (gpr_unref(&f->refs)) {
-    grpc_channel_args_destroy(f->merge_args);
-    gpr_free(f);
-  }
-}
+    grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory) {}
 
 static grpc_subchannel *client_channel_factory_create_subchannel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
-    grpc_subchannel_args *args) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
+    const grpc_subchannel_args *args) {
   connector *c = gpr_malloc(sizeof(*c));
-  grpc_channel_args *final_args =
-      grpc_channel_args_merge(args->args, f->merge_args);
-  grpc_subchannel *s;
   memset(c, 0, sizeof(*c));
   c->base.vtable = &connector_vtable;
   gpr_ref_init(&c->refs, 1);
@@ -196,23 +185,18 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
         grpc_http_connect_handshaker_create(proxy_name, args->server_name));
     gpr_free(proxy_name);
   }
-  args->args = final_args;
-  s = grpc_subchannel_create(exec_ctx, &c->base, args);
+  grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args);
   grpc_connector_unref(exec_ctx, &c->base);
-  grpc_channel_args_destroy(final_args);
   return s;
 }
 
 static grpc_channel *client_channel_factory_create_channel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const char *target, grpc_client_channel_type type,
-    grpc_channel_args *args) {
-  client_channel_factory *f = (client_channel_factory *)cc_factory;
-  grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
-  grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
-                                              GRPC_CLIENT_CHANNEL, NULL);
-  grpc_channel_args_destroy(final_args);
-  grpc_resolver *resolver = grpc_resolver_create(target);
+    const grpc_channel_args *args) {
+  grpc_channel *channel =
+      grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
+  grpc_resolver *resolver = grpc_resolver_create(target, args);
   if (!resolver) {
     GRPC_CHANNEL_INTERNAL_UNREF(exec_ctx, channel,
                                 "client_channel_factory_create_channel");
@@ -220,7 +204,7 @@ static grpc_channel *client_channel_factory_create_channel(
   }
 
   grpc_client_channel_finish_initialization(
-      exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
+      exec_ctx, grpc_channel_get_channel_stack(channel), resolver, cc_factory);
   GRPC_RESOLVER_UNREF(exec_ctx, resolver, "create_channel");
 
   return channel;
@@ -231,6 +215,9 @@ static const grpc_client_channel_factory_vtable client_channel_factory_vtable =
      client_channel_factory_create_subchannel,
      client_channel_factory_create_channel};
 
+static grpc_client_channel_factory client_channel_factory = {
+    &client_channel_factory_vtable};
+
 /* Create a client channel:
    Asynchronously: - resolve target
                    - connect to it (trying alternatives as presented)
@@ -244,16 +231,12 @@ grpc_channel *grpc_insecure_channel_create(const char *target,
       (target, args, reserved));
   GPR_ASSERT(!reserved);
 
-  client_channel_factory *f = gpr_malloc(sizeof(*f));
-  memset(f, 0, sizeof(*f));
-  f->base.vtable = &client_channel_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-  f->merge_args = grpc_channel_args_copy(args);
-
+  grpc_client_channel_factory *factory =
+      (grpc_client_channel_factory *)&client_channel_factory;
   grpc_channel *channel = client_channel_factory_create_channel(
-      &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
+      &exec_ctx, factory, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, args);
 
-  grpc_client_channel_factory_unref(&exec_ctx, &f->base);
+  grpc_client_channel_factory_unref(&exec_ctx, factory);
   grpc_exec_ctx_finish(&exec_ctx);
 
   return channel != NULL ? channel : grpc_lame_client_channel_create(
diff --git a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
index c5f4d497540f5ddc7fb9be403d11dd8ed3b456d5..29095af207619077e35cb1fe3bf1cfc6b2a81ad5 100644
--- a/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
+++ b/src/core/ext/transport/chttp2/client/secure/secure_channel_create.c
@@ -54,6 +54,10 @@
 #include "src/core/lib/surface/channel.h"
 #include "src/core/lib/tsi/transport_security_interface.h"
 
+//
+// connector
+//
+
 typedef struct {
   grpc_connector base;
   gpr_refcount refs;
@@ -216,10 +220,13 @@ static void connector_connect(grpc_exec_ctx *exec_ctx, grpc_connector *con,
 static const grpc_connector_vtable connector_vtable = {
     connector_ref, connector_unref, connector_shutdown, connector_connect};
 
+//
+// client_channel_factory
+//
+
 typedef struct {
   grpc_client_channel_factory base;
   gpr_refcount refs;
-  grpc_channel_args *merge_args;
   grpc_channel_security_connector *security_connector;
 } client_channel_factory;
 
@@ -235,19 +242,15 @@ static void client_channel_factory_unref(
   if (gpr_unref(&f->refs)) {
     GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                   "client_channel_factory");
-    grpc_channel_args_destroy(f->merge_args);
     gpr_free(f);
   }
 }
 
 static grpc_subchannel *client_channel_factory_create_subchannel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
-    grpc_subchannel_args *args) {
+    const grpc_subchannel_args *args) {
   client_channel_factory *f = (client_channel_factory *)cc_factory;
   connector *c = gpr_malloc(sizeof(*c));
-  grpc_channel_args *final_args =
-      grpc_channel_args_merge(args->args, f->merge_args);
-  grpc_subchannel *s;
   memset(c, 0, sizeof(*c));
   c->base.vtable = &connector_vtable;
   c->security_connector = f->security_connector;
@@ -261,25 +264,19 @@ static grpc_subchannel *client_channel_factory_create_subchannel(
   }
   gpr_mu_init(&c->mu);
   gpr_ref_init(&c->refs, 1);
-  args->args = final_args;
-  s = grpc_subchannel_create(exec_ctx, &c->base, args);
+  grpc_subchannel *s = grpc_subchannel_create(exec_ctx, &c->base, args);
   grpc_connector_unref(exec_ctx, &c->base);
-  grpc_channel_args_destroy(final_args);
   return s;
 }
 
 static grpc_channel *client_channel_factory_create_channel(
     grpc_exec_ctx *exec_ctx, grpc_client_channel_factory *cc_factory,
     const char *target, grpc_client_channel_type type,
-    grpc_channel_args *args) {
+    const grpc_channel_args *args) {
   client_channel_factory *f = (client_channel_factory *)cc_factory;
-
-  grpc_channel_args *final_args = grpc_channel_args_merge(args, f->merge_args);
-  grpc_channel *channel = grpc_channel_create(exec_ctx, target, final_args,
-                                              GRPC_CLIENT_CHANNEL, NULL);
-  grpc_channel_args_destroy(final_args);
-
-  grpc_resolver *resolver = grpc_resolver_create(target);
+  grpc_channel *channel =
+      grpc_channel_create(exec_ctx, target, args, GRPC_CLIENT_CHANNEL, NULL);
+  grpc_resolver *resolver = grpc_resolver_create(target, args);
   if (resolver != NULL) {
     grpc_client_channel_finish_initialization(
         exec_ctx, grpc_channel_get_channel_stack(channel), resolver, &f->base);
@@ -289,7 +286,6 @@ static grpc_channel *client_channel_factory_create_channel(
                                 "client_channel_factory_create_channel");
     channel = NULL;
   }
-
   return channel;
 }
 
@@ -306,19 +302,13 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
                                          const char *target,
                                          const grpc_channel_args *args,
                                          void *reserved) {
-  grpc_arg connector_arg;
-  grpc_channel_args *args_copy;
-  grpc_channel_args *new_args_from_connector;
-  grpc_channel_security_connector *security_connector;
-  client_channel_factory *f;
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
   GRPC_API_TRACE(
       "grpc_secure_channel_create(creds=%p, target=%s, args=%p, "
       "reserved=%p)",
       4, (creds, target, args, reserved));
   GPR_ASSERT(reserved == NULL);
-
+  // Make sure security connector does not already exist in args.
   if (grpc_find_security_connector_in_args(args) != NULL) {
     gpr_log(GPR_ERROR, "Cannot set security context in channel args.");
     grpc_exec_ctx_finish(&exec_ctx);
@@ -326,7 +316,9 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
         target, GRPC_STATUS_INTERNAL,
         "Security connector exists in channel args.");
   }
-
+  // Create security connector and construct new channel args.
+  grpc_channel_security_connector *security_connector;
+  grpc_channel_args *new_args_from_connector;
   if (grpc_channel_credentials_create_security_connector(
           creds, target, args, &security_connector, &new_args_from_connector) !=
       GRPC_SECURITY_OK) {
@@ -334,35 +326,30 @@ grpc_channel *grpc_secure_channel_create(grpc_channel_credentials *creds,
     return grpc_lame_client_channel_create(
         target, GRPC_STATUS_INTERNAL, "Failed to create security connector.");
   }
-
-  connector_arg = grpc_security_connector_to_arg(&security_connector->base);
-  args_copy = grpc_channel_args_copy_and_add(
+  grpc_arg connector_arg =
+      grpc_security_connector_to_arg(&security_connector->base);
+  grpc_channel_args *new_args = grpc_channel_args_copy_and_add(
       new_args_from_connector != NULL ? new_args_from_connector : args,
       &connector_arg, 1);
-
-  f = gpr_malloc(sizeof(*f));
-  memset(f, 0, sizeof(*f));
-  f->base.vtable = &client_channel_factory_vtable;
-  gpr_ref_init(&f->refs, 1);
-
-  f->merge_args = grpc_channel_args_copy(args_copy);
-  grpc_channel_args_destroy(args_copy);
   if (new_args_from_connector != NULL) {
     grpc_channel_args_destroy(new_args_from_connector);
   }
-
+  // Create client channel factory.
+  client_channel_factory *f = gpr_malloc(sizeof(*f));
+  memset(f, 0, sizeof(*f));
+  f->base.vtable = &client_channel_factory_vtable;
+  gpr_ref_init(&f->refs, 1);
   GRPC_SECURITY_CONNECTOR_REF(&security_connector->base,
                               "grpc_secure_channel_create");
   f->security_connector = security_connector;
-
+  // Create channel.
   grpc_channel *channel = client_channel_factory_create_channel(
-      &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, NULL);
-
+      &exec_ctx, &f->base, target, GRPC_CLIENT_CHANNEL_TYPE_REGULAR, new_args);
+  // Clean up.
   GRPC_SECURITY_CONNECTOR_UNREF(&f->security_connector->base,
                                 "client_channel_factory_create_channel");
-
+  grpc_channel_args_destroy(new_args);
   grpc_client_channel_factory_unref(&exec_ctx, &f->base);
   grpc_exec_ctx_finish(&exec_ctx);
-
   return channel; /* may be NULL */
 }
diff --git a/src/core/lib/channel/channel_args.c b/src/core/lib/channel/channel_args.c
index 2957d2c8188214c9bb4d1c1765df90b908a487b1..cfc072c0b563220b19d817efc8ea1583d58b5cce 100644
--- a/src/core/lib/channel/channel_args.c
+++ b/src/core/lib/channel/channel_args.c
@@ -66,22 +66,59 @@ static grpc_arg copy_arg(const grpc_arg *src) {
 grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
                                                   const grpc_arg *to_add,
                                                   size_t num_to_add) {
+  return grpc_channel_args_copy_and_add_and_remove(src, NULL, 0, to_add,
+                                                   num_to_add);
+}
+
+grpc_channel_args *grpc_channel_args_copy_and_remove(
+    const grpc_channel_args *src, const char **to_remove,
+    size_t num_to_remove) {
+  return grpc_channel_args_copy_and_add_and_remove(src, to_remove,
+                                                   num_to_remove, NULL, 0);
+}
+
+static bool should_remove_arg(const grpc_arg *arg, const char **to_remove,
+                              size_t num_to_remove) {
+  for (size_t i = 0; i < num_to_remove; ++i) {
+    if (strcmp(arg->key, to_remove[i]) == 0) return true;
+  }
+  return false;
+}
+
+grpc_channel_args *grpc_channel_args_copy_and_add_and_remove(
+    const grpc_channel_args *src, const char **to_remove, size_t num_to_remove,
+    const grpc_arg *to_add, size_t num_to_add) {
+  // Figure out how many args we'll be copying.
+  size_t num_args_to_copy = 0;
+  if (src != NULL) {
+    for (size_t i = 0; i < src->num_args; ++i) {
+      if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) {
+        ++num_args_to_copy;
+      }
+    }
+  }
+  // Create result.
   grpc_channel_args *dst = gpr_malloc(sizeof(grpc_channel_args));
-  size_t i;
-  size_t src_num_args = (src == NULL) ? 0 : src->num_args;
-  if (!src && !to_add) {
-    dst->num_args = 0;
+  dst->num_args = num_args_to_copy + num_to_add;
+  if (dst->num_args == 0) {
     dst->args = NULL;
     return dst;
   }
-  dst->num_args = src_num_args + num_to_add;
   dst->args = gpr_malloc(sizeof(grpc_arg) * dst->num_args);
-  for (i = 0; i < src_num_args; i++) {
-    dst->args[i] = copy_arg(&src->args[i]);
+  // Copy args from src that are not being removed.
+  size_t dst_idx = 0;
+  if (src != NULL) {
+    for (size_t i = 0; i < src->num_args; ++i) {
+      if (!should_remove_arg(&src->args[i], to_remove, num_to_remove)) {
+        dst->args[dst_idx++] = copy_arg(&src->args[i]);
+      }
+    }
   }
-  for (i = 0; i < num_to_add; i++) {
-    dst->args[i + src_num_args] = copy_arg(&to_add[i]);
+  // Add args from to_add.
+  for (size_t i = 0; i < num_to_add; ++i) {
+    dst->args[dst_idx++] = copy_arg(&to_add[i]);
   }
+  GPR_ASSERT(dst_idx == dst->num_args);
   return dst;
 }
 
diff --git a/src/core/lib/channel/channel_args.h b/src/core/lib/channel/channel_args.h
index a80340c0faf1964f2a5f3eb28f5a11baf0ca6f20..1e05303471d6920b0bd61423da70f7dc4386229a 100644
--- a/src/core/lib/channel/channel_args.h
+++ b/src/core/lib/channel/channel_args.h
@@ -51,6 +51,17 @@ grpc_channel_args *grpc_channel_args_copy_and_add(const grpc_channel_args *src,
                                                   const grpc_arg *to_add,
                                                   size_t num_to_add);
 
+/** Copies the arguments in \a src except for those whose keys are in
+    \a to_remove. */
+grpc_channel_args *grpc_channel_args_copy_and_remove(
+    const grpc_channel_args *src, const char **to_remove, size_t num_to_remove);
+
+/** Copies the arguments from \a src except for those whose keys are in
+    \a to_remove and appends the arguments in \a to_add. */
+grpc_channel_args *grpc_channel_args_copy_and_add_and_remove(
+    const grpc_channel_args *src, const char **to_remove, size_t num_to_remove,
+    const grpc_arg *to_add, size_t num_to_add);
+
 /** Concatenate args from \a a and \a b into a new instance */
 grpc_channel_args *grpc_channel_args_merge(const grpc_channel_args *a,
                                            const grpc_channel_args *b);
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 0ffb0e351c3dedce66ea812294b291b01534960f..105ce9d4bfc6070c0257a2097e1621196c2cdd0f 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -250,7 +250,6 @@ CORE_SOURCE_FILES = [
   'src/core/ext/client_channel/resolver.c',
   'src/core/ext/client_channel/resolver_factory.c',
   'src/core/ext/client_channel/resolver_registry.c',
-  'src/core/ext/client_channel/resolver_result.c',
   'src/core/ext/client_channel/subchannel.c',
   'src/core/ext/client_channel/subchannel_index.c',
   'src/core/ext/client_channel/uri_parser.c',
diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
index 07723c229d291fe594016e622182a96c6f00151c..ffa167a0e7899a9850b56b0b2dbb88ab1d638cbe 100644
--- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
@@ -37,6 +37,7 @@
 #include <grpc/support/alloc.h>
 
 #include "src/core/ext/client_channel/resolver_registry.h"
+#include "src/core/lib/channel/channel_args.h"
 #include "src/core/lib/iomgr/resolve_address.h"
 #include "src/core/lib/iomgr/timer.h"
 #include "test/core/util/test_config.h"
@@ -103,7 +104,7 @@ int main(int argc, char **argv) {
 
   grpc_resolver *resolver = create_resolver("dns:test");
 
-  grpc_resolver_result *result = (grpc_resolver_result *)1;
+  grpc_channel_args *result = (grpc_channel_args *)1;
 
   grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
   gpr_event ev1;
@@ -122,7 +123,7 @@ int main(int argc, char **argv) {
   GPR_ASSERT(wait_loop(30, &ev2));
   GPR_ASSERT(result != NULL);
 
-  grpc_resolver_result_unref(&exec_ctx, result);
+  grpc_channel_args_destroy(result);
   GRPC_RESOLVER_UNREF(&exec_ctx, resolver, "test");
   grpc_exec_ctx_finish(&exec_ctx);
 
diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.c b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
index c39052cd9dd6570722df3a4e869bfa813bcbf3b9..ebf311ab83f8eac76a14d19e40a02788ccf50b01 100644
--- a/test/core/client_channel/resolvers/sockaddr_resolver_test.c
+++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
@@ -38,21 +38,23 @@
 #include <grpc/support/string_util.h>
 
 #include "src/core/ext/client_channel/resolver_registry.h"
-#include "src/core/ext/client_channel/resolver_result.h"
+#include "src/core/lib/channel/channel_args.h"
 
 #include "test/core/util/test_config.h"
 
 typedef struct on_resolution_arg {
   char *expected_server_name;
-  grpc_resolver_result *resolver_result;
+  grpc_channel_args *resolver_result;
 } on_resolution_arg;
 
 void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
   on_resolution_arg *res = arg;
-  const char *server_name =
-      grpc_resolver_result_get_server_name(res->resolver_result);
-  GPR_ASSERT(strcmp(res->expected_server_name, server_name) == 0);
-  grpc_resolver_result_unref(exec_ctx, res->resolver_result);
+  const grpc_arg *channel_arg =
+      grpc_channel_args_find(res->resolver_result, GRPC_ARG_SERVER_NAME);
+  GPR_ASSERT(channel_arg != NULL);
+  GPR_ASSERT(channel_arg->type == GRPC_ARG_STRING);
+  GPR_ASSERT(strcmp(res->expected_server_name, channel_arg->value.string) == 0);
+  grpc_channel_args_destroy(res->resolver_result);
 }
 
 static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
diff --git a/test/core/end2end/fake_resolver.c b/test/core/end2end/fake_resolver.c
index ed9721775073942902fce327bcd2bb979e77f79a..54cc381612197c358c934438168fb475c53a94ec 100644
--- a/test/core/end2end/fake_resolver.c
+++ b/test/core/end2end/fake_resolver.c
@@ -42,6 +42,7 @@
 #include <grpc/support/port_platform.h>
 #include <grpc/support/string_util.h>
 
+#include "src/core/ext/client_channel/lb_policy_factory.h"
 #include "src/core/ext/client_channel/method_config.h"
 #include "src/core/ext/client_channel/parse_address.h"
 #include "src/core/ext/client_channel/resolver_registry.h"
@@ -59,7 +60,7 @@ typedef struct {
   grpc_resolver base;
 
   // passed-in parameters
-  char* target_name;  // the path component of the uri passed in
+  grpc_channel_args* channel_args;
   grpc_lb_addresses* addresses;
   char* lb_policy_name;
   grpc_method_config_table* method_config_table;
@@ -71,14 +72,14 @@ typedef struct {
   // pending next completion, or NULL
   grpc_closure* next_completion;
   // target result address for next completion
-  grpc_resolver_result** target_result;
+  grpc_channel_args** target_result;
 } fake_resolver;
 
 static void fake_resolver_destroy(grpc_exec_ctx* exec_ctx, grpc_resolver* gr) {
   fake_resolver* r = (fake_resolver*)gr;
   gpr_mu_destroy(&r->mu);
-  gpr_free(r->target_name);
-  grpc_lb_addresses_destroy(r->addresses, NULL /* user_data_destroy */);
+  grpc_channel_args_destroy(r->channel_args);
+  grpc_lb_addresses_destroy(r->addresses);
   gpr_free(r->lb_policy_name);
   grpc_method_config_table_unref(r->method_config_table);
   gpr_free(r);
@@ -100,16 +101,21 @@ static void fake_resolver_maybe_finish_next_locked(grpc_exec_ctx* exec_ctx,
                                                    fake_resolver* r) {
   if (r->next_completion != NULL && !r->published) {
     r->published = true;
-    grpc_channel_args* lb_policy_args = NULL;
+    grpc_arg new_args[3];
+    size_t num_args = 0;
+    new_args[num_args++] = grpc_lb_addresses_create_channel_arg(r->addresses);
     if (r->method_config_table != NULL) {
-      const grpc_arg arg =
+      new_args[num_args++] =
           grpc_method_config_table_create_channel_arg(r->method_config_table);
-      lb_policy_args = grpc_channel_args_copy_and_add(NULL /* src */, &arg, 1);
     }
-    *r->target_result = grpc_resolver_result_create(
-        r->target_name,
-        grpc_lb_addresses_copy(r->addresses, NULL /* user_data_copy */),
-        r->lb_policy_name, lb_policy_args);
+    if (r->lb_policy_name != NULL) {
+      new_args[num_args].type = GRPC_ARG_STRING;
+      new_args[num_args].key = GRPC_ARG_LB_POLICY_NAME;
+      new_args[num_args].value.string = r->lb_policy_name;
+      ++num_args;
+    }
+    *r->target_result =
+        grpc_channel_args_copy_and_add(r->channel_args, new_args, num_args);
     grpc_exec_ctx_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE, NULL);
     r->next_completion = NULL;
   }
@@ -125,7 +131,7 @@ static void fake_resolver_channel_saw_error(grpc_exec_ctx* exec_ctx,
 }
 
 static void fake_resolver_next(grpc_exec_ctx* exec_ctx, grpc_resolver* resolver,
-                               grpc_resolver_result** target_result,
+                               grpc_channel_args** target_result,
                                grpc_closure* on_complete) {
   fake_resolver* r = (fake_resolver*)resolver;
   gpr_mu_lock(&r->mu);
@@ -168,7 +174,8 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
   gpr_slice_buffer path_parts;
   gpr_slice_buffer_init(&path_parts);
   gpr_slice_split(path_slice, ",", &path_parts);
-  grpc_lb_addresses* addresses = grpc_lb_addresses_create(path_parts.count);
+  grpc_lb_addresses* addresses =
+      grpc_lb_addresses_create(path_parts.count, NULL /* user_data_vtable */);
   bool errors_found = false;
   for (size_t i = 0; i < addresses->num_addresses; i++) {
     grpc_uri ith_uri = *args->uri;
@@ -184,7 +191,7 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
   gpr_slice_buffer_destroy(&path_parts);
   gpr_slice_unref(path_slice);
   if (errors_found) {
-    grpc_lb_addresses_destroy(addresses, NULL /* user_data_destroy */);
+    grpc_lb_addresses_destroy(addresses);
     return NULL;
   }
   // Construct method config table.
@@ -229,7 +236,12 @@ static grpc_resolver* fake_resolver_create(grpc_resolver_factory* factory,
   // Instantiate resolver.
   fake_resolver* r = gpr_malloc(sizeof(fake_resolver));
   memset(r, 0, sizeof(*r));
-  r->target_name = gpr_strdup(args->uri->path);
+  grpc_arg server_name_arg;
+  server_name_arg.type = GRPC_ARG_STRING;
+  server_name_arg.key = GRPC_ARG_SERVER_NAME;
+  server_name_arg.value.string = args->uri->path;
+  r->channel_args =
+      grpc_channel_args_copy_and_add(args->args, &server_name_arg, 1);
   r->addresses = addresses;
   r->lb_policy_name =
       gpr_strdup(grpc_uri_get_query_arg(args->uri, "lb_policy"));
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index b1d3ce92f6aa8f4a3bb99c805603ef162832025f..7af0fb997e23e1325d30b68b2229b2999bb992f5 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -636,7 +636,7 @@ TEST_P(End2endTest, SimpleRpcWithCustomeUserAgentPrefix) {
   auto iter = trailing_metadata.find("user-agent");
   EXPECT_TRUE(iter != trailing_metadata.end());
   grpc::string expected_prefix = user_agent_prefix_ + " grpc-c++/";
-  EXPECT_TRUE(iter->second.starts_with(expected_prefix));
+  EXPECT_TRUE(iter->second.starts_with(expected_prefix)) << iter->second;
 }
 
 TEST_P(End2endTest, MultipleRpcsWithVariedBinaryMetadataValue) {
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index 827159ab3ee51ebad762d2f1f0b7137a41747d5f..05e10e765a0120a0c8657008f0de39e4bf5cfdf5 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -935,7 +935,6 @@ src/core/ext/client_channel/parse_address.h \
 src/core/ext/client_channel/resolver.h \
 src/core/ext/client_channel/resolver_factory.h \
 src/core/ext/client_channel/resolver_registry.h \
-src/core/ext/client_channel/resolver_result.h \
 src/core/ext/client_channel/subchannel.h \
 src/core/ext/client_channel/subchannel_index.h \
 src/core/ext/client_channel/uri_parser.h \
@@ -1132,7 +1131,6 @@ src/core/ext/client_channel/parse_address.c \
 src/core/ext/client_channel/resolver.c \
 src/core/ext/client_channel/resolver_factory.c \
 src/core/ext/client_channel/resolver_registry.c \
-src/core/ext/client_channel/resolver_result.c \
 src/core/ext/client_channel/subchannel.c \
 src/core/ext/client_channel/subchannel_index.c \
 src/core/ext/client_channel/uri_parser.c \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 60138a49a2e15fe6021afcad7cf632507f3b46f0..46a83c247948bc014ebe9365f8b00f783b1fd62b 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -6818,7 +6818,6 @@
       "src/core/ext/client_channel/resolver.h", 
       "src/core/ext/client_channel/resolver_factory.h", 
       "src/core/ext/client_channel/resolver_registry.h", 
-      "src/core/ext/client_channel/resolver_result.h", 
       "src/core/ext/client_channel/subchannel.h", 
       "src/core/ext/client_channel/subchannel_index.h", 
       "src/core/ext/client_channel/uri_parser.h"
@@ -6856,8 +6855,6 @@
       "src/core/ext/client_channel/resolver_factory.h", 
       "src/core/ext/client_channel/resolver_registry.c", 
       "src/core/ext/client_channel/resolver_registry.h", 
-      "src/core/ext/client_channel/resolver_result.c", 
-      "src/core/ext/client_channel/resolver_result.h", 
       "src/core/ext/client_channel/subchannel.c", 
       "src/core/ext/client_channel/subchannel.h", 
       "src/core/ext/client_channel/subchannel_index.c", 
diff --git a/tools/run_tests/tests.json b/tools/run_tests/tests.json
index c86b14f63eb26dc981649d156427fc1d42209229..5cb50cc999c90d47b080654321ff1be167d06b07 100644
--- a/tools/run_tests/tests.json
+++ b/tools/run_tests/tests.json
@@ -1306,6 +1306,7 @@
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
+    "exclude_iomgrs": [], 
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
@@ -1321,6 +1322,7 @@
     ], 
     "cpu_cost": 1.0, 
     "exclude_configs": [], 
+    "exclude_iomgrs": [], 
     "flaky": false, 
     "gtest": false, 
     "language": "c", 
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj b/vsprojects/vcxproj/grpc/grpc.vcxproj
index 7870234aec2d8455d623cdf9d71105d88b3119bd..47cf51bbd5297278cd7562b5bfb2ae49ecf146d6 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj
@@ -444,7 +444,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@@ -816,8 +815,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">
diff --git a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
index 760ac313bb80bfda668f3fc0f822d922265bdd06..06a52af0a07b70b87f7634cda90787dfd785e841 100644
--- a/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc/grpc.vcxproj.filters
@@ -520,9 +520,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
-      <Filter>src\core\ext\client_channel</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -1154,9 +1151,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h">
-      <Filter>src\core\ext\client_channel</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
index 577264d3260e2a78fbdc9191207d6aabfafb5fa2..ffc3b1f28046fc02fc84a1c77d42b2a6675a9d39 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj
@@ -410,7 +410,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_factory.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h" />
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.h" />
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\uri_parser.h" />
@@ -734,8 +733,6 @@
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
     </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel_index.c">
diff --git a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
index 9b3c6943633682c21f84bf4045f68424386962a4..ed882d637573566e9e62ebd4e91031593a5ec4cd 100644
--- a/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vcxproj/grpc_unsecure/grpc_unsecure.vcxproj.filters
@@ -448,9 +448,6 @@
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
-    <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.c">
-      <Filter>src\core\ext\client_channel</Filter>
-    </ClCompile>
     <ClCompile Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.c">
       <Filter>src\core\ext\client_channel</Filter>
     </ClCompile>
@@ -995,9 +992,6 @@
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_registry.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>
-    <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\resolver_result.h">
-      <Filter>src\core\ext\client_channel</Filter>
-    </ClInclude>
     <ClInclude Include="$(SolutionDir)\..\src\core\ext\client_channel\subchannel.h">
       <Filter>src\core\ext\client_channel</Filter>
     </ClInclude>